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 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 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 /********************************************************************* 401 * _aligned_msize (MSVCR100.@) 402 */ 403 size_t CDECL _aligned_msize(void *p, MSVCRT_size_t alignment, MSVCRT_size_t offset) 404 { 405 void **alloc_ptr; 406 407 if(!MSVCRT_CHECK_PMT(p)) return -1; 408 409 if(alignment < sizeof(void*)) 410 alignment = sizeof(void*); 411 412 alloc_ptr = SAVED_PTR(p); 413 return _msize(*alloc_ptr)-alignment-sizeof(void*); 414 } 415 416 /********************************************************************* 417 * calloc (MSVCRT.@) 418 */ 419 void* CDECL MSVCRT_calloc(MSVCRT_size_t count, MSVCRT_size_t size) 420 { 421 MSVCRT_size_t bytes = count*size; 422 423 if (size && bytes / size != count) 424 { 425 *MSVCRT__errno() = MSVCRT_ENOMEM; 426 return NULL; 427 } 428 429 return msvcrt_heap_alloc(HEAP_ZERO_MEMORY, bytes); 430 } 431 432 /********************************************************************* 433 * _calloc_base (UCRTBASE.@) 434 */ 435 void* CDECL _calloc_base(MSVCRT_size_t count, MSVCRT_size_t size) 436 { 437 return MSVCRT_calloc(count, size); 438 } 439 440 /********************************************************************* 441 * free (MSVCRT.@) 442 */ 443 void CDECL MSVCRT_free(void* ptr) 444 { 445 msvcrt_heap_free(ptr); 446 } 447 448 /********************************************************************* 449 * _free_base (UCRTBASE.@) 450 */ 451 void CDECL _free_base(void* ptr) 452 { 453 msvcrt_heap_free(ptr); 454 } 455 456 /********************************************************************* 457 * malloc (MSVCRT.@) 458 */ 459 void* CDECL MSVCRT_malloc(MSVCRT_size_t size) 460 { 461 void *ret = msvcrt_heap_alloc(0, size); 462 if (!ret) 463 *MSVCRT__errno() = MSVCRT_ENOMEM; 464 return ret; 465 } 466 467 /********************************************************************* 468 * _malloc_base (UCRTBASE.@) 469 */ 470 void* CDECL _malloc_base(MSVCRT_size_t size) 471 { 472 return MSVCRT_malloc(size); 473 } 474 475 /********************************************************************* 476 * realloc (MSVCRT.@) 477 */ 478 void* CDECL MSVCRT_realloc(void* ptr, MSVCRT_size_t size) 479 { 480 if (!ptr) return MSVCRT_malloc(size); 481 if (size) return msvcrt_heap_realloc(0, ptr, size); 482 MSVCRT_free(ptr); 483 return NULL; 484 } 485 486 /********************************************************************* 487 * _realloc_base (UCRTBASE.@) 488 */ 489 void* CDECL _realloc_base(void* ptr, MSVCRT_size_t size) 490 { 491 return MSVCRT_realloc(ptr, size); 492 } 493 494 /********************************************************************* 495 * _recalloc (MSVCR100.@) 496 */ 497 void* CDECL _recalloc(void *mem, MSVCRT_size_t num, MSVCRT_size_t size) 498 { 499 MSVCRT_size_t old_size; 500 void *ret; 501 502 if(!mem) 503 return MSVCRT_calloc(num, size); 504 505 size = num*size; 506 old_size = _msize(mem); 507 508 ret = MSVCRT_realloc(mem, size); 509 if(!ret) { 510 *MSVCRT__errno() = MSVCRT_ENOMEM; 511 return NULL; 512 } 513 514 if(size>old_size) 515 memset((BYTE*)ret+old_size, 0, size-old_size); 516 return ret; 517 } 518 519 /********************************************************************* 520 * __p__amblksiz (MSVCRT.@) 521 */ 522 unsigned int* CDECL __p__amblksiz(void) 523 { 524 return &MSVCRT_amblksiz; 525 } 526 527 /********************************************************************* 528 * _get_sbh_threshold (MSVCRT.@) 529 */ 530 MSVCRT_size_t CDECL _get_sbh_threshold(void) 531 { 532 return MSVCRT_sbh_threshold; 533 } 534 535 /********************************************************************* 536 * _set_sbh_threshold (MSVCRT.@) 537 */ 538 int CDECL _set_sbh_threshold(MSVCRT_size_t threshold) 539 { 540 #ifdef _WIN64 541 return 0; 542 #else 543 if(threshold > 1016) 544 return 0; 545 546 if(!sb_heap) 547 { 548 sb_heap = HeapCreate(0, 0, 0); 549 if(!sb_heap) 550 return 0; 551 } 552 553 MSVCRT_sbh_threshold = (threshold+0xf) & ~0xf; 554 return 1; 555 #endif 556 } 557 558 /********************************************************************* 559 * _aligned_free (MSVCRT.@) 560 */ 561 void CDECL _aligned_free(void *memblock) 562 { 563 TRACE("(%p)\n", memblock); 564 565 if (memblock) 566 { 567 void **saved = SAVED_PTR(memblock); 568 MSVCRT_free(*saved); 569 } 570 } 571 572 /********************************************************************* 573 * _aligned_offset_malloc (MSVCRT.@) 574 */ 575 void * CDECL _aligned_offset_malloc(MSVCRT_size_t size, MSVCRT_size_t alignment, MSVCRT_size_t offset) 576 { 577 void *memblock, *temp, **saved; 578 TRACE("(%lu, %lu, %lu)\n", size, alignment, offset); 579 580 /* alignment must be a power of 2 */ 581 if ((alignment & (alignment - 1)) != 0) 582 { 583 *MSVCRT__errno() = MSVCRT_EINVAL; 584 return NULL; 585 } 586 587 /* offset must be less than size */ 588 if (offset && offset >= size) 589 { 590 *MSVCRT__errno() = MSVCRT_EINVAL; 591 return NULL; 592 } 593 594 /* don't align to less than void pointer size */ 595 if (alignment < sizeof(void *)) 596 alignment = sizeof(void *); 597 598 /* allocate enough space for void pointer and alignment */ 599 temp = MSVCRT_malloc(size + alignment + sizeof(void *)); 600 601 if (!temp) 602 return NULL; 603 604 /* adjust pointer for proper alignment and offset */ 605 memblock = ALIGN_PTR(temp, alignment, offset); 606 607 /* Save the real allocation address below returned address */ 608 /* so it can be found later to free. */ 609 saved = SAVED_PTR(memblock); 610 *saved = temp; 611 612 return memblock; 613 } 614 615 /********************************************************************* 616 * _aligned_malloc (MSVCRT.@) 617 */ 618 void * CDECL _aligned_malloc(MSVCRT_size_t size, MSVCRT_size_t alignment) 619 { 620 TRACE("(%lu, %lu)\n", size, alignment); 621 return _aligned_offset_malloc(size, alignment, 0); 622 } 623 624 /********************************************************************* 625 * _aligned_offset_realloc (MSVCRT.@) 626 */ 627 void * CDECL _aligned_offset_realloc(void *memblock, MSVCRT_size_t size, 628 MSVCRT_size_t alignment, MSVCRT_size_t offset) 629 { 630 void * temp, **saved; 631 MSVCRT_size_t old_padding, new_padding, old_size; 632 TRACE("(%p, %lu, %lu, %lu)\n", memblock, size, alignment, offset); 633 634 if (!memblock) 635 return _aligned_offset_malloc(size, alignment, offset); 636 637 /* alignment must be a power of 2 */ 638 if ((alignment & (alignment - 1)) != 0) 639 { 640 *MSVCRT__errno() = MSVCRT_EINVAL; 641 return NULL; 642 } 643 644 /* offset must be less than size */ 645 if (offset >= size) 646 { 647 *MSVCRT__errno() = MSVCRT_EINVAL; 648 return NULL; 649 } 650 651 if (size == 0) 652 { 653 _aligned_free(memblock); 654 return NULL; 655 } 656 657 /* don't align to less than void pointer size */ 658 if (alignment < sizeof(void *)) 659 alignment = sizeof(void *); 660 661 /* make sure alignment and offset didn't change */ 662 saved = SAVED_PTR(memblock); 663 if (memblock != ALIGN_PTR(*saved, alignment, offset)) 664 { 665 *MSVCRT__errno() = MSVCRT_EINVAL; 666 return NULL; 667 } 668 669 old_padding = (char *)memblock - (char *)*saved; 670 671 /* Get previous size of block */ 672 old_size = _msize(*saved); 673 if (old_size == -1) 674 { 675 /* It seems this function was called with an invalid pointer. Bail out. */ 676 return NULL; 677 } 678 679 /* Adjust old_size to get amount of actual data in old block. */ 680 if (old_size < old_padding) 681 { 682 /* Shouldn't happen. Something's weird, so bail out. */ 683 return NULL; 684 } 685 old_size -= old_padding; 686 687 temp = MSVCRT_realloc(*saved, size + alignment + sizeof(void *)); 688 689 if (!temp) 690 return NULL; 691 692 /* adjust pointer for proper alignment and offset */ 693 memblock = ALIGN_PTR(temp, alignment, offset); 694 695 /* Save the real allocation address below returned address */ 696 /* so it can be found later to free. */ 697 saved = SAVED_PTR(memblock); 698 699 new_padding = (char *)memblock - (char *)temp; 700 701 /* 702 Memory layout of old block is as follows: 703 +-------+---------------------+-+--------------------------+-----------+ 704 | ... | "old_padding" bytes | | ... "old_size" bytes ... | ... | 705 +-------+---------------------+-+--------------------------+-----------+ 706 ^ ^ ^ 707 | | | 708 *saved saved memblock 709 710 Memory layout of new block is as follows: 711 +-------+-----------------------------+-+----------------------+-------+ 712 | ... | "new_padding" bytes | | ... "size" bytes ... | ... | 713 +-------+-----------------------------+-+----------------------+-------+ 714 ^ ^ ^ 715 | | | 716 temp saved memblock 717 718 However, in the new block, actual data is still written as follows 719 (because it was copied by MSVCRT_realloc): 720 +-------+---------------------+--------------------------------+-------+ 721 | ... | "old_padding" bytes | ... "old_size" bytes ... | ... | 722 +-------+---------------------+--------------------------------+-------+ 723 ^ ^ ^ 724 | | | 725 temp saved memblock 726 727 Therefore, min(old_size,size) bytes of actual data have to be moved 728 from the offset they were at in the old block (temp + old_padding), 729 to the offset they have to be in the new block (temp + new_padding == memblock). 730 */ 731 if (new_padding != old_padding) 732 memmove((char *)memblock, (char *)temp + old_padding, (old_size < size) ? old_size : size); 733 734 *saved = temp; 735 736 return memblock; 737 } 738 739 /********************************************************************* 740 * _aligned_realloc (MSVCRT.@) 741 */ 742 void * CDECL _aligned_realloc(void *memblock, MSVCRT_size_t size, MSVCRT_size_t alignment) 743 { 744 TRACE("(%p, %lu, %lu)\n", memblock, size, alignment); 745 return _aligned_offset_realloc(memblock, size, alignment, 0); 746 } 747 748 /********************************************************************* 749 * memmove_s (MSVCRT.@) 750 */ 751 int CDECL MSVCRT_memmove_s(void *dest, MSVCRT_size_t numberOfElements, const void *src, MSVCRT_size_t count) 752 { 753 TRACE("(%p %lu %p %lu)\n", dest, numberOfElements, src, count); 754 755 if(!count) 756 return 0; 757 758 if (!MSVCRT_CHECK_PMT(dest != NULL)) return MSVCRT_EINVAL; 759 if (!MSVCRT_CHECK_PMT(src != NULL)) return MSVCRT_EINVAL; 760 if (!MSVCRT_CHECK_PMT_ERR( count <= numberOfElements, MSVCRT_ERANGE )) return MSVCRT_ERANGE; 761 762 memmove(dest, src, count); 763 return 0; 764 } 765 766 /********************************************************************* 767 * wmemmove_s (MSVCR100.@) 768 */ 769 int CDECL wmemmove_s(MSVCRT_wchar_t *dest, MSVCRT_size_t numberOfElements, 770 const MSVCRT_wchar_t *src, MSVCRT_size_t count) 771 { 772 TRACE("(%p %lu %p %lu)\n", dest, numberOfElements, src, count); 773 774 if (!count) 775 return 0; 776 777 /* Native does not seem to conform to 6.7.1.2.3 in 778 * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1225.pdf 779 * in that it does not zero the output buffer on constraint violation. 780 */ 781 if (!MSVCRT_CHECK_PMT(dest != NULL)) return MSVCRT_EINVAL; 782 if (!MSVCRT_CHECK_PMT(src != NULL)) return MSVCRT_EINVAL; 783 if (!MSVCRT_CHECK_PMT_ERR(count <= numberOfElements, MSVCRT_ERANGE)) return MSVCRT_ERANGE; 784 785 memmove(dest, src, sizeof(MSVCRT_wchar_t)*count); 786 return 0; 787 } 788 789 /********************************************************************* 790 * memcpy_s (MSVCRT.@) 791 */ 792 int CDECL MSVCRT_memcpy_s(void *dest, MSVCRT_size_t numberOfElements, const void *src, MSVCRT_size_t count) 793 { 794 TRACE("(%p %lu %p %lu)\n", dest, numberOfElements, src, count); 795 796 if(!count) 797 return 0; 798 799 if (!MSVCRT_CHECK_PMT(dest != NULL)) return MSVCRT_EINVAL; 800 if (!MSVCRT_CHECK_PMT(src != NULL)) 801 { 802 memset(dest, 0, numberOfElements); 803 return MSVCRT_EINVAL; 804 } 805 if (!MSVCRT_CHECK_PMT_ERR( count <= numberOfElements, MSVCRT_ERANGE )) 806 { 807 memset(dest, 0, numberOfElements); 808 return MSVCRT_ERANGE; 809 } 810 811 memcpy(dest, src, count); 812 return 0; 813 } 814 815 /********************************************************************* 816 * wmemcpy_s (MSVCR100.@) 817 */ 818 int CDECL wmemcpy_s(MSVCRT_wchar_t *dest, MSVCRT_size_t numberOfElements, 819 const MSVCRT_wchar_t *src, MSVCRT_size_t count) 820 { 821 TRACE("(%p %lu %p %lu)\n", dest, numberOfElements, src, count); 822 823 if (!count) 824 return 0; 825 826 if (!MSVCRT_CHECK_PMT(dest != NULL)) return MSVCRT_EINVAL; 827 828 if (!MSVCRT_CHECK_PMT(src != NULL)) { 829 memset(dest, 0, numberOfElements*sizeof(MSVCRT_wchar_t)); 830 return MSVCRT_EINVAL; 831 } 832 if (!MSVCRT_CHECK_PMT_ERR(count <= numberOfElements, MSVCRT_ERANGE)) { 833 memset(dest, 0, numberOfElements*sizeof(MSVCRT_wchar_t)); 834 return MSVCRT_ERANGE; 835 } 836 837 memcpy(dest, src, sizeof(MSVCRT_wchar_t)*count); 838 return 0; 839 } 840 841 /********************************************************************* 842 * strncpy_s (MSVCRT.@) 843 */ 844 int CDECL MSVCRT_strncpy_s(char *dest, MSVCRT_size_t numberOfElements, 845 const char *src, MSVCRT_size_t count) 846 { 847 MSVCRT_size_t i, end; 848 849 TRACE("(%s %lu %s %lu)\n", dest, numberOfElements, src, count); 850 851 if(!count) { 852 if(dest && numberOfElements) 853 *dest = 0; 854 return 0; 855 } 856 857 if (!MSVCRT_CHECK_PMT(dest != NULL)) return MSVCRT_EINVAL; 858 if (!MSVCRT_CHECK_PMT(src != NULL)) return MSVCRT_EINVAL; 859 if (!MSVCRT_CHECK_PMT(numberOfElements != 0)) return MSVCRT_EINVAL; 860 861 if(count!=MSVCRT__TRUNCATE && count<numberOfElements) 862 end = count; 863 else 864 end = numberOfElements-1; 865 866 for(i=0; i<end && src[i]; i++) 867 dest[i] = src[i]; 868 869 if(!src[i] || end==count || count==MSVCRT__TRUNCATE) { 870 dest[i] = '\0'; 871 return 0; 872 } 873 874 MSVCRT_INVALID_PMT("dest[numberOfElements] is too small", MSVCRT_EINVAL); 875 dest[0] = '\0'; 876 return MSVCRT_EINVAL; 877 } 878 879 BOOL msvcrt_init_heap(void) 880 { 881 #ifdef __REACTOS__ 882 heap = GetProcessHeap(); 883 #else 884 heap = HeapCreate(0, 0, 0); 885 #endif 886 return heap != NULL; 887 } 888 889 void msvcrt_destroy_heap(void) 890 { 891 HeapDestroy(heap); 892 if(sb_heap) 893 HeapDestroy(sb_heap); 894 } 895