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