00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "ntrtlp.h"
00022
#include "heap.h"
00023
#include "heappriv.h"
00024
00025
#ifdef NTHEAP_ENABLED
00026
#include "heapp.h"
00027
#endif // NTHEAP_ENABLED
00028
00029
00030
00031
00032
00033
00034
00035
00036 typedef struct _RTL_HEAP_USAGE_INTERNAL {
00037 PVOID
Base;
00038 SIZE_T
ReservedSize;
00039 SIZE_T
CommittedSize;
00040 PRTL_HEAP_USAGE_ENTRY
FreeList;
00041 PRTL_HEAP_USAGE_ENTRY
LargeEntriesSentinal;
00042 ULONG
Reserved;
00043 }
RTL_HEAP_USAGE_INTERNAL, *
PRTL_HEAP_USAGE_INTERNAL;
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 HEAP_LOCK RtlpProcessHeapsListLock;
00054
00055
00056
00057
00058
00059 #define RTLP_STATIC_HEAP_LIST_SIZE 16
00060
00061 PHEAP RtlpProcessHeapsListBuffer[
RTLP_STATIC_HEAP_LIST_SIZE ];
00062
00063
00064
00065
00066
00067
00068 PHEAP RtlpGlobalTagHeap =
NULL;
00069
00070
00071
00072
00073
00074
00075 static WCHAR
RtlpPseudoTagNameBuffer[ 24 ];
00076
00077 BOOLEAN
00078
RtlpGrowBlockInPlace (
00079 IN
PHEAP Heap,
00080 IN ULONG Flags,
00081 IN
PHEAP_ENTRY BusyBlock,
00082 IN SIZE_T Size,
00083 IN SIZE_T AllocationIndex
00084 );
00085
00086 PVOID
00087
RtlDebugReAllocateHeap (
00088 IN PVOID HeapHandle,
00089 IN ULONG Flags,
00090 IN PVOID BaseAddress,
00091 IN SIZE_T Size
00092 );
00093
00094 BOOLEAN
00095
RtlDebugGetUserInfoHeap (
00096 IN PVOID HeapHandle,
00097 IN ULONG Flags,
00098 IN PVOID BaseAddress,
00099 OUT PVOID *UserValue OPTIONAL,
00100 OUT PULONG UserFlags OPTIONAL
00101 );
00102
00103 BOOLEAN
00104
RtlDebugSetUserValueHeap (
00105 IN PVOID HeapHandle,
00106 IN ULONG Flags,
00107 IN PVOID BaseAddress,
00108 IN PVOID UserValue
00109 );
00110
00111 BOOLEAN
00112
RtlDebugSetUserFlagsHeap (
00113 IN PVOID HeapHandle,
00114 IN ULONG Flags,
00115 IN PVOID BaseAddress,
00116 IN ULONG UserFlagsReset,
00117 IN ULONG UserFlagsSet
00118 );
00119
00120 SIZE_T
00121
RtlDebugCompactHeap (
00122 IN PVOID HeapHandle,
00123 IN ULONG Flags
00124 );
00125
00126
NTSTATUS
00127
RtlDebugCreateTagHeap (
00128 IN PVOID HeapHandle,
00129 IN ULONG Flags,
00130 IN PWSTR TagPrefix OPTIONAL,
00131 IN PWSTR TagNames
00132 );
00133
00134 PWSTR
00135
RtlDebugQueryTagHeap (
00136 IN PVOID HeapHandle,
00137 IN ULONG Flags,
00138 IN USHORT TagIndex,
00139 IN BOOLEAN ResetCounters,
00140 OUT PRTL_HEAP_TAG_INFO TagInfo OPTIONAL
00141 );
00142
00143
NTSTATUS
00144
RtlDebugUsageHeap (
00145 IN PVOID HeapHandle,
00146 IN ULONG Flags,
00147 IN OUT PRTL_HEAP_USAGE Usage
00148 );
00149
00150 BOOLEAN
00151
RtlDebugWalkHeap (
00152 IN PVOID HeapHandle,
00153 IN OUT PRTL_HEAP_WALK_ENTRY Entry
00154 );
00155
00156
PHEAP_TAG_ENTRY
00157
RtlpAllocateTags (
00158
PHEAP Heap,
00159 ULONG NumberOfTags
00160 );
00161
00162 PRTL_HEAP_USAGE_ENTRY
00163
RtlpFreeHeapUsageEntry (
00164 PRTL_HEAP_USAGE_INTERNAL Buffer,
00165 PRTL_HEAP_USAGE_ENTRY p
00166 );
00167
00168
NTSTATUS
00169
RtlpAllocateHeapUsageEntry (
00170 PRTL_HEAP_USAGE_INTERNAL Buffer,
00171 PRTL_HEAP_USAGE_ENTRY *pp
00172 );
00173
00174
00175
00176
00177
00178
NTSTATUS
00179 RtlInitializeHeapManager(
00180 VOID
00181 )
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 {
00200 PPEB Peb = NtCurrentPeb();
00201
00202
#if DBG
00203
00204
00205
00206
00207
00208
if (
sizeof(
HEAP_ENTRY ) !=
sizeof(
HEAP_ENTRY_EXTRA )) {
00209
00210
HeapDebugPrint((
"Heap header and extra header sizes disagree\n" ));
00211
00212
HeapDebugBreak(
NULL );
00213 }
00214
00215
if (
sizeof(
HEAP_ENTRY ) !=
CHECK_HEAP_TAIL_SIZE) {
00216
00217
HeapDebugPrint((
"Heap header and tail fill sizes disagree\n" ));
00218
00219
HeapDebugBreak(
NULL );
00220 }
00221
00222
if (
sizeof(
HEAP_FREE_ENTRY ) != (2 *
sizeof(
HEAP_ENTRY ))) {
00223
00224
HeapDebugPrint((
"Heap header and free header sizes disagree\n" ));
00225
00226
HeapDebugBreak(
NULL );
00227 }
00228
00229
#endif // DBG
00230
00231
00232
00233
00234
00235 Peb->NumberOfHeaps = 0;
00236 Peb->MaximumNumberOfHeaps =
RTLP_STATIC_HEAP_LIST_SIZE;
00237 Peb->ProcessHeaps =
RtlpProcessHeapsListBuffer;
00238
00239
#ifdef NTHEAP_ENABLED
00240
{
00241 (
VOID) RtlInitializeNtHeapManager();
00242 }
00243
#endif // NTHEAP_ENABLED
00244
00245
00246
00247
00248
00249
return RtlInitializeLockRoutine( &
RtlpProcessHeapsListLock.
Lock );
00250 }
00251
00252
00253
00254
00255
00256
00257
VOID
00258 RtlProtectHeap (
00259 IN PVOID HeapHandle,
00260 IN BOOLEAN MakeReadOnly
00261 )
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 {
00284
PHEAP Heap;
00285 UCHAR SegmentIndex;
00286
PHEAP_SEGMENT Segment;
00287 MEMORY_BASIC_INFORMATION VaInfo;
00288
NTSTATUS Status;
00289 PVOID Address;
00290 PVOID ProtectAddress;
00291 SIZE_T
Size;
00292 ULONG OldProtect;
00293 ULONG NewProtect;
00294
00295 Heap = (
PHEAP)
HeapHandle;
00296
00297
00298
00299
00300
00301
00302
for (SegmentIndex=0; SegmentIndex<
HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) {
00303
00304 Segment = Heap->
Segments[ SegmentIndex ];
00305
00306
if ( Segment ) {
00307
00308
00309
00310
00311
00312
00313 Address = Segment->
BaseAddress;
00314
00315
while ((ULONG_PTR)Address < (ULONG_PTR)(Segment->
LastValidEntry)) {
00316
00317
00318
00319
00320
00321
Status = ZwQueryVirtualMemory( NtCurrentProcess(),
00322 Address,
00323 MemoryBasicInformation,
00324 &VaInfo,
00325
sizeof(VaInfo),
00326
NULL );
00327
00328
if (!
NT_SUCCESS(
Status )) {
00329
00330
HeapDebugPrint((
"VirtualQuery Failed 0x%08x %x\n", Address,
Status ));
00331
00332
return;
00333 }
00334
00335
00336
00337
00338
00339
if (VaInfo.State == MEM_COMMIT) {
00340
00341
Size = VaInfo.RegionSize;
00342
00343 ProtectAddress = Address;
00344
00345
if (MakeReadOnly) {
00346
00347 NewProtect = PAGE_READONLY;
00348
00349 }
else {
00350
00351 NewProtect = PAGE_READWRITE;
00352 }
00353
00354
Status = ZwProtectVirtualMemory( NtCurrentProcess(),
00355 &ProtectAddress,
00356 &
Size,
00357 NewProtect,
00358 &OldProtect );
00359
00360
if (!
NT_SUCCESS(
Status )) {
00361
00362
HeapDebugPrint((
"VirtualProtect Failed 0x%08x %x\n", Address,
Status ));
00363
00364
return;
00365 }
00366 }
00367
00368
00369
00370
00371
00372 Address = (PVOID)((PCHAR)Address + VaInfo.RegionSize);
00373 }
00374 }
00375 }
00376
00377
00378
00379
00380
00381
return;
00382 }
00383
00384
00385
00386
00387
00388
00389 BOOLEAN
00390 RtlLockHeap (
00391 IN PVOID HeapHandle
00392 )
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 {
00413
PHEAP Heap = (
PHEAP)
HeapHandle;
00414
00415
RTL_PAGED_CODE();
00416
00417
00418
00419
00420
00421
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
00422
RtlpDebugPageHeapLock(
HeapHandle ));
00423
00424
00425
00426
00427
00428
if (!
RtlpCheckHeapSignature( Heap,
"RtlLockHeap" )) {
00429
00430
return FALSE;
00431 }
00432
00433
00434
00435
00436
00437
00438
if (!(Heap->
Flags & HEAP_NO_SERIALIZE)) {
00439
00440
RtlAcquireLockRoutine( Heap->
LockVariable );
00441
00442 Heap->
LookasideLockCount += 1;
00443 }
00444
00445
return TRUE;
00446 }
00447
00448
00449
00450
00451
00452
00453 BOOLEAN
00454 RtlUnlockHeap (
00455 IN PVOID HeapHandle
00456 )
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 {
00477
PHEAP Heap = (
PHEAP)
HeapHandle;
00478
00479
RTL_PAGED_CODE();
00480
00481
00482
00483
00484
00485
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
00486
RtlpDebugPageHeapUnlock(
HeapHandle ));
00487
00488
00489
00490
00491
00492
if (!
RtlpCheckHeapSignature( Heap,
"RtlUnlockHeap" )) {
00493
00494
return FALSE;
00495 }
00496
00497
00498
00499
00500
00501
00502
if (!(Heap->
Flags & HEAP_NO_SERIALIZE)) {
00503
00504 Heap->
LookasideLockCount -= 1;
00505
00506
RtlReleaseLockRoutine( Heap->
LockVariable );
00507 }
00508
00509
return TRUE;
00510 }
00511
00512
00513
00514
00515
00516
00517 PVOID
00518 RtlReAllocateHeap (
00519 IN PVOID HeapHandle,
00520 IN ULONG Flags,
00521 IN PVOID BaseAddress,
00522 IN SIZE_T Size
00523 )
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554 {
00555
PHEAP Heap = (
PHEAP)
HeapHandle;
00556 SIZE_T AllocationSize;
00557
PHEAP_ENTRY BusyBlock, NewBusyBlock;
00558
PHEAP_ENTRY_EXTRA OldExtraStuff, NewExtraStuff;
00559 SIZE_T FreeSize;
00560 BOOLEAN LockAcquired =
FALSE;
00561 PVOID NewBaseAddress;
00562
PHEAP_FREE_ENTRY SplitBlock, SplitBlock2;
00563 SIZE_T OldSize;
00564 SIZE_T AllocationIndex;
00565 SIZE_T OldAllocationIndex;
00566 UCHAR FreeFlags;
00567
NTSTATUS Status;
00568 PVOID DeCommitAddress;
00569 SIZE_T DeCommitSize;
00570 EXCEPTION_RECORD ExceptionRecord;
00571
00572
00573
00574
00575
00576
if (BaseAddress ==
NULL) {
00577
00578
SET_LAST_STATUS( STATUS_SUCCESS );
00579
00580
return NULL;
00581 }
00582
00583
#ifdef NTHEAP_ENABLED
00584
{
00585
if (Heap->
Flags & NTHEAP_ENABLED_FLAG) {
00586
00587
return RtlReAllocateNtHeap(
HeapHandle, Flags, BaseAddress,
Size );
00588 }
00589 }
00590
#endif // NTHEAP_ENABLED
00591
00592
00593
00594
00595
00596 Flags |= Heap->
ForceFlags;
00597
00598
00599
00600
00601
00602
if (
DEBUG_HEAP( Flags)) {
00603
00604
return RtlDebugReAllocateHeap(
HeapHandle, Flags, BaseAddress,
Size );
00605 }
00606
00607
00608
00609
00610
00611
if (
Size > 0x7fffffff) {
00612
00613
SET_LAST_STATUS( STATUS_NO_MEMORY );
00614
00615
return NULL;
00616 }
00617
00618
00619
00620
00621
00622
00623
00624 AllocationSize = ((
Size ?
Size : 1) + Heap->
AlignRound) & Heap->
AlignMask;
00625
00626
if ((Flags &
HEAP_NEED_EXTRA_FLAGS) ||
00627 (Heap->
PseudoTagEntries !=
NULL) ||
00628 ((((
PHEAP_ENTRY)BaseAddress)-1)->Flags &
HEAP_ENTRY_EXTRA_PRESENT)) {
00629
00630 AllocationSize +=
sizeof(
HEAP_ENTRY_EXTRA );
00631 }
00632
00633
try {
00634
00635
00636
00637
00638
00639
if (!(Flags & HEAP_NO_SERIALIZE)) {
00640
00641
RtlAcquireLockRoutine( Heap->
LockVariable );
00642
00643 LockAcquired =
TRUE;
00644
00645
00646
00647
00648
00649
00650 Flags ^= HEAP_NO_SERIALIZE;
00651 }
00652
00653
try {
00654
00655
00656
00657
00658
00659 BusyBlock = (
PHEAP_ENTRY)BaseAddress - 1;
00660
00661
00662
00663
00664
00665
if (!(BusyBlock->
Flags &
HEAP_ENTRY_BUSY)) {
00666
00667
SET_LAST_STATUS( STATUS_INVALID_PARAMETER );
00668
00669
00670
00671
00672
00673 leave;
00674
00675
00676
00677
00678
00679
00680
00681 }
else if (BusyBlock->
Flags &
HEAP_ENTRY_VIRTUAL_ALLOC) {
00682
00683 OldSize =
RtlpGetSizeOfBigBlock( BusyBlock );
00684
00685 OldAllocationIndex = (OldSize + BusyBlock->
Size) >>
HEAP_GRANULARITY_SHIFT;
00686
00687
00688
00689
00690
00691
00692 AllocationSize += FIELD_OFFSET(
HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock );
00693 AllocationSize =
ROUND_UP_TO_POWER2( AllocationSize,
PAGE_SIZE );
00694
00695
00696
00697
00698
00699 }
else {
00700
00701 OldAllocationIndex = BusyBlock->
Size;
00702
00703 OldSize = (OldAllocationIndex <<
HEAP_GRANULARITY_SHIFT) -
00704 BusyBlock->
UnusedBytes;
00705 }
00706
00707
00708
00709
00710
00711 AllocationIndex = AllocationSize >>
HEAP_GRANULARITY_SHIFT;
00712
00713
00714
00715
00716
00717
00718
00719
00720
if (AllocationIndex <= OldAllocationIndex) {
00721
00722
00723
00724
00725
00726
00727
if (AllocationIndex + 1 == OldAllocationIndex) {
00728
00729 AllocationIndex += 1;
00730 AllocationSize +=
sizeof(
HEAP_ENTRY );
00731 }
00732
00733
00734
00735
00736
00737
if (BusyBlock->
Flags &
HEAP_ENTRY_VIRTUAL_ALLOC) {
00738
00739
00740
00741
00742
00743 BusyBlock->
Size = (
USHORT)(AllocationSize -
Size);
00744
00745 }
else if (BusyBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
00746
00747
00748
00749
00750
00751
00752 OldExtraStuff = (
PHEAP_ENTRY_EXTRA)(BusyBlock + BusyBlock->
Size - 1);
00753
00754 NewExtraStuff = (
PHEAP_ENTRY_EXTRA)(BusyBlock + AllocationIndex - 1);
00755
00756 *NewExtraStuff = *OldExtraStuff;
00757
00758
00759
00760
00761
00762
if (
IS_HEAP_TAGGING_ENABLED()) {
00763
00764 NewExtraStuff->
TagIndex =
00765
RtlpUpdateTagEntry( Heap,
00766 NewExtraStuff->
TagIndex,
00767 OldAllocationIndex,
00768 AllocationIndex,
00769
ReAllocationAction );
00770 }
00771
00772 BusyBlock->
UnusedBytes = (UCHAR)(AllocationSize -
Size);
00773
00774 }
else {
00775
00776
00777
00778
00779
00780
if (
IS_HEAP_TAGGING_ENABLED()) {
00781
00782 BusyBlock->
SmallTagIndex = (UCHAR)
00783
RtlpUpdateTagEntry( Heap,
00784 BusyBlock->
SmallTagIndex,
00785 BusyBlock->
Size,
00786 AllocationIndex,
00787
ReAllocationAction );
00788 }
00789
00790 BusyBlock->
UnusedBytes = (UCHAR)(AllocationSize -
Size);
00791 }
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
if (
Size > OldSize) {
00802
00803
00804
00805
00806
00807
if (Flags & HEAP_ZERO_MEMORY) {
00808
00809 RtlZeroMemory( (PCHAR)BaseAddress + OldSize,
00810
Size - OldSize );
00811
00812
00813
00814
00815
00816 }
else if (Heap->
Flags & HEAP_FREE_CHECKING_ENABLED) {
00817
00818 SIZE_T PartialBytes, ExtraSize;
00819
00820 PartialBytes = OldSize & (
sizeof( ULONG ) - 1);
00821
00822
if (PartialBytes) {
00823
00824 PartialBytes = 4 - PartialBytes;
00825 }
00826
00827
if (
Size > (OldSize + PartialBytes)) {
00828
00829 ExtraSize = (
Size - (OldSize + PartialBytes)) & ~(
sizeof( ULONG ) - 1);
00830
00831
if (ExtraSize != 0) {
00832
00833 RtlFillMemoryUlong( (PCHAR)(BusyBlock + 1) + OldSize + PartialBytes,
00834 ExtraSize,
00835
ALLOC_HEAP_FILL );
00836 }
00837 }
00838 }
00839 }
00840
00841
if (Heap->
Flags & HEAP_TAIL_CHECKING_ENABLED) {
00842
00843 RtlFillMemory( (PCHAR)(BusyBlock + 1) +
Size,
00844
CHECK_HEAP_TAIL_SIZE,
00845
CHECK_HEAP_TAIL_FILL );
00846 }
00847
00848
00849
00850
00851
00852
00853
00854
if (AllocationIndex != OldAllocationIndex) {
00855
00856 FreeFlags = BusyBlock->
Flags & ~
HEAP_ENTRY_BUSY;
00857
00858
if (FreeFlags &
HEAP_ENTRY_VIRTUAL_ALLOC) {
00859
00860
PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock;
00861
00862 VirtualAllocBlock = CONTAINING_RECORD( BusyBlock,
HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock );
00863
00864
if (
IS_HEAP_TAGGING_ENABLED()) {
00865
00866 VirtualAllocBlock->
ExtraStuff.
TagIndex =
00867
RtlpUpdateTagEntry( Heap,
00868 VirtualAllocBlock->
ExtraStuff.
TagIndex,
00869 OldAllocationIndex,
00870 AllocationIndex,
00871
VirtualReAllocationAction );
00872 }
00873
00874 DeCommitAddress = (PCHAR)VirtualAllocBlock + AllocationSize;
00875
00876 DeCommitSize = (OldAllocationIndex <<
HEAP_GRANULARITY_SHIFT) -
00877 AllocationSize;
00878
00879
Status = ZwFreeVirtualMemory( NtCurrentProcess(),
00880 (PVOID *)&DeCommitAddress,
00881 &DeCommitSize,
00882 MEM_RELEASE );
00883
00884
if (!
NT_SUCCESS(
Status )) {
00885
00886
HeapDebugPrint((
"Unable to release memory at %p for %p bytes - Status == %x\n",
00887 DeCommitAddress, DeCommitSize,
Status ));
00888
00889
HeapDebugBreak(
NULL );
00890
00891 }
else {
00892
00893 VirtualAllocBlock->
CommitSize -= DeCommitSize;
00894 }
00895
00896 }
else {
00897
00898
00899
00900
00901
00902
00903 SplitBlock = (
PHEAP_FREE_ENTRY)(BusyBlock + AllocationIndex);
00904
00905 SplitBlock->
Flags = FreeFlags;
00906
00907 SplitBlock->
PreviousSize = (
USHORT)AllocationIndex;
00908
00909 SplitBlock->
SegmentIndex = BusyBlock->
SegmentIndex;
00910
00911 FreeSize = BusyBlock->
Size - AllocationIndex;
00912
00913 BusyBlock->
Size = (
USHORT)AllocationIndex;
00914
00915 BusyBlock->
Flags &= ~
HEAP_ENTRY_LAST_ENTRY;
00916
00917
00918
00919
00920
00921
00922
if (FreeFlags &
HEAP_ENTRY_LAST_ENTRY) {
00923
00924
PHEAP_SEGMENT Segment;
00925
00926 Segment = Heap->
Segments[SplitBlock->
SegmentIndex];
00927 Segment->
LastEntryInSegment = (
PHEAP_ENTRY)SplitBlock;
00928
00929 SplitBlock->
Size = (
USHORT)FreeSize;
00930
00931
RtlpInsertFreeBlockDirect( Heap, SplitBlock, (
USHORT)FreeSize );
00932
00933 Heap->
TotalFreeSize += FreeSize;
00934
00935 }
else {
00936
00937
00938
00939
00940
00941
00942 SplitBlock2 = (
PHEAP_FREE_ENTRY)((
PHEAP_ENTRY)SplitBlock + FreeSize);
00943
00944
if (SplitBlock2->
Flags &
HEAP_ENTRY_BUSY) {
00945
00946 SplitBlock->
Size = (
USHORT)FreeSize;
00947
00948 ((
PHEAP_FREE_ENTRY)((
PHEAP_ENTRY)SplitBlock + FreeSize))->PreviousSize = (
USHORT)FreeSize;
00949
00950
RtlpInsertFreeBlockDirect( Heap, SplitBlock, (
USHORT)FreeSize );
00951
00952 Heap->
TotalFreeSize += FreeSize;
00953
00954 }
else {
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 SplitBlock->
Flags = SplitBlock2->
Flags;
00967
00968
RtlpRemoveFreeBlock( Heap, SplitBlock2 );
00969
00970 Heap->
TotalFreeSize -= SplitBlock2->
Size;
00971
00972 FreeSize += SplitBlock2->
Size;
00973
00974
if (FreeSize <=
HEAP_MAXIMUM_BLOCK_SIZE) {
00975
00976 SplitBlock->
Size = (
USHORT)FreeSize;
00977
00978
if (!(SplitBlock->
Flags &
HEAP_ENTRY_LAST_ENTRY)) {
00979
00980 ((
PHEAP_FREE_ENTRY)((
PHEAP_ENTRY)SplitBlock + FreeSize))->PreviousSize = (
USHORT)FreeSize;
00981
00982 }
else {
00983
00984
PHEAP_SEGMENT Segment;
00985
00986 Segment = Heap->
Segments[SplitBlock->
SegmentIndex];
00987 Segment->
LastEntryInSegment = (
PHEAP_ENTRY)SplitBlock;
00988 }
00989
00990
RtlpInsertFreeBlockDirect( Heap, SplitBlock, (
USHORT)FreeSize );
00991
00992 Heap->
TotalFreeSize += FreeSize;
00993
00994 }
else {
00995
00996
RtlpInsertFreeBlock( Heap, SplitBlock, FreeSize );
00997 }
00998 }
00999 }
01000 }
01001 }
01002
01003 }
else {
01004
01005
01006
01007
01008
01009
01010
01011
01012
if ((BusyBlock->
Flags &
HEAP_ENTRY_VIRTUAL_ALLOC) ||
01013 !
RtlpGrowBlockInPlace( Heap, Flags, BusyBlock,
Size, AllocationIndex )) {
01014
01015
01016
01017
01018
01019
01020
01021
if (Flags & HEAP_REALLOC_IN_PLACE_ONLY) {
01022
01023
#if DBG
01024
01025
#endif
01026
01027 BaseAddress =
NULL;
01028
01029 }
else {
01030
01031
01032
01033
01034
01035 Flags &= ~HEAP_TAG_MASK;
01036
01037
01038
01039
01040
01041
01042
01043
if (BusyBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
01044
01045 Flags &= ~HEAP_SETTABLE_USER_FLAGS;
01046
01047 Flags |= HEAP_SETTABLE_USER_VALUE |
01048 ((BusyBlock->
Flags &
HEAP_ENTRY_SETTABLE_FLAGS) << 4);
01049
01050 OldExtraStuff =
RtlpGetExtraStuffPointer( BusyBlock );
01051
01052
try {
01053
01054
if ((OldExtraStuff->
TagIndex != 0) &&
01055 !(OldExtraStuff->
TagIndex & HEAP_PSEUDO_TAG_FLAG)) {
01056
01057 Flags |= OldExtraStuff->
TagIndex << HEAP_TAG_SHIFT;
01058 }
01059
01060 } except (
EXCEPTION_EXECUTE_HANDLER) {
01061
01062 BusyBlock->
Flags &= ~
HEAP_ENTRY_EXTRA_PRESENT;
01063 }
01064
01065 }
else if (BusyBlock->
SmallTagIndex != 0) {
01066
01067
01068
01069
01070
01071
01072
01073 Flags |= BusyBlock->
SmallTagIndex << HEAP_TAG_SHIFT;
01074 }
01075
01076
01077
01078
01079
01080 NewBaseAddress =
RtlAllocateHeap(
HeapHandle,
01081 Flags & ~HEAP_ZERO_MEMORY,
01082
Size );
01083
01084
if (NewBaseAddress !=
NULL) {
01085
01086
01087
01088
01089
01090
01091
01092 NewBusyBlock = (
PHEAP_ENTRY)NewBaseAddress - 1;
01093
01094
if (NewBusyBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
01095
01096 NewExtraStuff =
RtlpGetExtraStuffPointer( NewBusyBlock );
01097
01098
if (BusyBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
01099
01100 OldExtraStuff =
RtlpGetExtraStuffPointer( BusyBlock );
01101
01102 NewExtraStuff->
Settable = OldExtraStuff->
Settable;
01103
01104 }
else {
01105
01106 RtlZeroMemory( NewExtraStuff,
sizeof( *NewExtraStuff ));
01107 }
01108 }
01109
01110
01111
01112
01113
01114 RtlMoveMemory( NewBaseAddress, BaseAddress,
Size < OldSize ?
Size : OldSize );
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
if (
Size > OldSize && (Flags & HEAP_ZERO_MEMORY)) {
01125
01126 RtlZeroMemory( (PCHAR)NewBaseAddress + OldSize,
01127
Size - OldSize );
01128 }
01129
01130
01131
01132
01133
01134
RtlFreeHeap(
HeapHandle,
01135 Flags,
01136 BaseAddress );
01137 }
01138
01139 BaseAddress = NewBaseAddress;
01140 }
01141 }
01142 }
01143
01144
if ((BaseAddress ==
NULL) && (Flags & HEAP_GENERATE_EXCEPTIONS)) {
01145
01146
01147
01148
01149
01150 ExceptionRecord.ExceptionCode = STATUS_NO_MEMORY;
01151 ExceptionRecord.ExceptionRecord = (PEXCEPTION_RECORD)
NULL;
01152 ExceptionRecord.NumberParameters = 1;
01153 ExceptionRecord.ExceptionFlags = 0;
01154 ExceptionRecord.ExceptionInformation[ 0 ] = AllocationSize;
01155
01156
RtlRaiseException( &ExceptionRecord );
01157 }
01158
01159 } except( GetExceptionCode() == STATUS_NO_MEMORY ?
EXCEPTION_CONTINUE_SEARCH :
01160
EXCEPTION_EXECUTE_HANDLER ) {
01161
01162
SET_LAST_STATUS( GetExceptionCode() );
01163 BaseAddress =
NULL;
01164
01165 }
01166
01167 } finally {
01168
01169
01170
01171
01172
01173
if (LockAcquired) {
01174
01175
RtlReleaseLockRoutine( Heap->
LockVariable );
01176 }
01177 }
01178
01179
01180
01181
01182
01183
return BaseAddress;
01184 }
01185
01186
01187
01188
01189
01190
01191 BOOLEAN
01192 RtlGetUserInfoHeap (
01193 IN PVOID HeapHandle,
01194 IN ULONG Flags,
01195 IN PVOID BaseAddress,
01196 OUT PVOID *UserValue OPTIONAL,
01197 OUT PULONG UserFlags OPTIONAL
01198 )
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230 {
01231
PHEAP Heap = (
PHEAP)
HeapHandle;
01232
PHEAP_ENTRY BusyBlock;
01233
PHEAP_ENTRY_EXTRA ExtraStuff;
01234 BOOLEAN LockAcquired =
FALSE;
01235 BOOLEAN Result;
01236
01237
01238
01239
01240
01241 Flags |= Heap->
ForceFlags;
01242
01243
01244
01245
01246
01247
if (
DEBUG_HEAP( Flags )) {
01248
01249
return RtlDebugGetUserInfoHeap(
HeapHandle, Flags, BaseAddress, UserValue, UserFlags );
01250 }
01251
01252 Result =
FALSE;
01253
01254
try {
01255
01256
try {
01257
01258
01259
01260
01261
01262
if (!(Flags & HEAP_NO_SERIALIZE)) {
01263
01264
RtlAcquireLockRoutine( Heap->
LockVariable );
01265
01266 LockAcquired =
TRUE;
01267 }
01268
01269
01270
01271
01272
01273 BusyBlock = (
PHEAP_ENTRY)BaseAddress - 1;
01274
01275
01276
01277
01278
01279
if (!(BusyBlock->
Flags &
HEAP_ENTRY_BUSY)) {
01280
01281
SET_LAST_STATUS( STATUS_INVALID_PARAMETER );
01282
01283 }
else {
01284
01285
01286
01287
01288
01289
01290
if (BusyBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
01291
01292
01293
01294
01295
01296
01297
01298 ExtraStuff =
RtlpGetExtraStuffPointer( BusyBlock );
01299
01300
if (ARGUMENT_PRESENT( UserValue )) {
01301
01302 *UserValue = (PVOID)ExtraStuff->
Settable;
01303 }
01304 }
01305
01306
01307
01308
01309
01310
01311
if (ARGUMENT_PRESENT( UserFlags )) {
01312
01313 *UserFlags = (BusyBlock->
Flags &
HEAP_ENTRY_SETTABLE_FLAGS) << 4;
01314 }
01315
01316
01317
01318
01319
01320
01321 Result =
TRUE;
01322 }
01323
01324 } except(
EXCEPTION_EXECUTE_HANDLER ) {
01325
01326
SET_LAST_STATUS( GetExceptionCode() );
01327
01328 Result =
FALSE;
01329 }
01330
01331 } finally {
01332
01333
01334
01335
01336
01337
if (LockAcquired) {
01338
01339
RtlReleaseLockRoutine( Heap->
LockVariable );
01340 }
01341 }
01342
01343
01344
01345
01346
01347
return Result;
01348 }
01349
01350
01351
01352
01353
01354
01355 BOOLEAN
01356 RtlSetUserValueHeap (
01357 IN PVOID HeapHandle,
01358 IN ULONG Flags,
01359 IN PVOID BaseAddress,
01360 IN PVOID UserValue
01361 )
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390 {
01391
PHEAP Heap = (
PHEAP)
HeapHandle;
01392
PHEAP_ENTRY BusyBlock;
01393
PHEAP_ENTRY_EXTRA ExtraStuff;
01394 BOOLEAN LockAcquired =
FALSE;
01395 BOOLEAN Result;
01396
01397
01398
01399
01400
01401 Flags |= Heap->
ForceFlags;
01402
01403
01404
01405
01406
01407
if (
DEBUG_HEAP( Flags )) {
01408
01409
return RtlDebugSetUserValueHeap(
HeapHandle, Flags, BaseAddress, UserValue );
01410 }
01411
01412 Result =
FALSE;
01413
01414
try {
01415
01416
01417
01418
01419
01420
if (!(Flags & HEAP_NO_SERIALIZE)) {
01421
01422
RtlAcquireLockRoutine( Heap->
LockVariable );
01423
01424 LockAcquired =
TRUE;
01425 }
01426
01427
01428
01429
01430
01431 BusyBlock = (
PHEAP_ENTRY)BaseAddress - 1;
01432
01433
01434
01435
01436
01437
if (!(BusyBlock->
Flags &
HEAP_ENTRY_BUSY)) {
01438
01439
SET_LAST_STATUS( STATUS_INVALID_PARAMETER );
01440
01441
01442
01443
01444
01445
01446 }
else if (BusyBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
01447
01448 ExtraStuff =
RtlpGetExtraStuffPointer( BusyBlock );
01449
01450 ExtraStuff->
Settable = (ULONG_PTR)UserValue;
01451
01452 Result =
TRUE;
01453 }
01454
01455 } finally {
01456
01457
01458
01459
01460
01461
if (LockAcquired) {
01462
01463
RtlReleaseLockRoutine( Heap->
LockVariable );
01464 }
01465 }
01466
01467
01468
01469
01470
01471
return Result;
01472 }
01473
01474
01475
01476
01477
01478
01479 BOOLEAN
01480 RtlSetUserFlagsHeap (
01481 IN PVOID HeapHandle,
01482 IN ULONG Flags,
01483 IN PVOID BaseAddress,
01484 IN ULONG UserFlagsReset,
01485 IN ULONG UserFlagsSet
01486 )
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510 {
01511
PHEAP Heap = (
PHEAP)
HeapHandle;
01512
PHEAP_ENTRY BusyBlock;
01513 BOOLEAN LockAcquired =
FALSE;
01514 BOOLEAN Result =
FALSE;
01515
01516
01517
01518
01519
01520 Flags |= Heap->
ForceFlags;
01521
01522
01523
01524
01525
01526
if (
DEBUG_HEAP( Flags )) {
01527
01528
return RtlDebugSetUserFlagsHeap(
HeapHandle, Flags, BaseAddress, UserFlagsReset, UserFlagsSet );
01529 }
01530
01531
try {
01532
01533
01534
01535
01536
01537
if (!(Flags & HEAP_NO_SERIALIZE)) {
01538
01539
RtlAcquireLockRoutine( Heap->
LockVariable );
01540
01541 LockAcquired =
TRUE;
01542 }
01543
01544
try {
01545
01546
01547
01548
01549
01550 BusyBlock = (
PHEAP_ENTRY)BaseAddress - 1;
01551
01552
01553
01554
01555
01556
if (!(BusyBlock->
Flags &
HEAP_ENTRY_BUSY)) {
01557
01558
SET_LAST_STATUS( STATUS_INVALID_PARAMETER );
01559
01560 }
else {
01561
01562
01563
01564
01565
01566
01567
01568
01569 BusyBlock->
Flags &= ~(UserFlagsReset >> 4);
01570 BusyBlock->
Flags |= (UserFlagsSet >> 4);
01571
01572 Result =
TRUE;
01573 }
01574
01575 } except(
EXCEPTION_EXECUTE_HANDLER ) {
01576
01577
SET_LAST_STATUS( GetExceptionCode() );
01578
01579 Result =
FALSE;
01580 }
01581
01582 } finally {
01583
01584
01585
01586
01587
01588
if (LockAcquired) {
01589
01590
RtlReleaseLockRoutine( Heap->
LockVariable );
01591 }
01592 }
01593
01594
return Result;
01595 }
01596
01597
01598
01599
01600
01601
01602 ULONG
01603 RtlCreateTagHeap (
01604 IN PVOID HeapHandle,
01605 IN ULONG Flags,
01606 IN PWSTR TagPrefix OPTIONAL,
01607 IN PWSTR TagNames
01608 )
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642 {
01643
PHEAP Heap = (
PHEAP)
HeapHandle;
01644 BOOLEAN LockAcquired =
FALSE;
01645 ULONG TagIndex;
01646 ULONG NumberOfTags, MaxTagNameLength, TagPrefixLength;
01647 PWSTR s, s1, HeapName;
01648
PHEAP_TAG_ENTRY TagEntry;
01649 ULONG Result;
01650
01651
01652
01653
01654
01655
if (!
IS_HEAP_TAGGING_ENABLED()) {
01656
01657
return 0;
01658 }
01659
01660
01661
01662
01663
01664
01665
if (
RtlpGlobalTagHeap ==
NULL) {
01666
01667
RtlpGlobalTagHeap =
RtlAllocateHeap( RtlProcessHeap( ), HEAP_ZERO_MEMORY,
sizeof(
HEAP ));
01668
01669
if (
RtlpGlobalTagHeap ==
NULL) {
01670
01671
return 0;
01672 }
01673 }
01674
01675
try {
01676
01677
01678
01679
01680
01681
01682
if (Heap !=
NULL) {
01683
01684
01685
01686
01687
01688
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle, 0 );
01689
01690
01691
01692
01693
01694
if (
DEBUG_HEAP( Flags )) {
01695
01696 Result =
RtlDebugCreateTagHeap(
HeapHandle, Flags, TagPrefix, TagNames );
01697 leave;
01698 }
01699
01700
01701
01702
01703
01704 Flags |= Heap->
ForceFlags;
01705
01706
if (!(Flags & HEAP_NO_SERIALIZE)) {
01707
01708
RtlAcquireLockRoutine( Heap->
LockVariable );
01709
01710 LockAcquired =
TRUE;
01711 }
01712 }
01713
01714
01715
01716
01717
01718 TagIndex = 0;
01719 NumberOfTags = 0;
01720
01721
01722
01723
01724
01725
01726
if (*TagNames ==
L'!') {
01727
01728 HeapName = TagNames + 1;
01729
01730
01731
01732
01733
01734
01735
while (*TagNames++) { NOTHING; }
01736
01737 }
else {
01738
01739 HeapName =
NULL;
01740 }
01741
01742
01743
01744
01745
01746 s = TagNames;
01747
01748
while (*s) {
01749
01750
while (*s++) { NOTHING; }
01751
01752 NumberOfTags += 1;
01753 }
01754
01755
01756
01757
01758
01759
if (NumberOfTags > 0) {
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769 TagEntry =
RtlpAllocateTags( Heap, NumberOfTags );
01770
01771
if (TagEntry !=
NULL) {
01772
01773 MaxTagNameLength = (
sizeof( TagEntry->
TagName ) /
sizeof( WCHAR )) - 1;
01774
01775 TagIndex = TagEntry->
TagIndex;
01776
01777
01778
01779
01780
01781
01782
if (TagIndex == 0) {
01783
01784
if (HeapName !=
NULL ) {
01785
01786
01787
01788
01789
01790
01791 wcsncpy( TagEntry->
TagName, HeapName, MaxTagNameLength );
01792 }
01793
01794
01795
01796
01797
01798
01799 TagEntry += 1;
01800
01801 TagIndex = TagEntry->
TagIndex;
01802
01803
01804
01805
01806
01807
01808
01809 }
else if (TagIndex == HEAP_GLOBAL_TAG) {
01810
01811 wcsncpy( TagEntry->
TagName,
L"GlobalTags", MaxTagNameLength );
01812
01813 TagEntry += 1;
01814
01815 TagIndex = TagEntry->
TagIndex;
01816 }
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
if ((ARGUMENT_PRESENT( TagPrefix )) &&
01827 (TagPrefixLength = wcslen( TagPrefix ))) {
01828
01829
if (TagPrefixLength >= MaxTagNameLength-4) {
01830
01831 TagPrefix =
NULL;
01832
01833 }
else {
01834
01835 MaxTagNameLength -= TagPrefixLength;
01836 }
01837
01838 }
else {
01839
01840 TagPrefix =
NULL;
01841 }
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852 s = TagNames;
01853
01854
while (*s) {
01855
01856 s1 = TagEntry->
TagName;
01857
01858
01859
01860
01861
01862
if (ARGUMENT_PRESENT( TagPrefix )) {
01863
01864 wcscpy( s1, TagPrefix );
01865
01866 s1 += TagPrefixLength;
01867 }
01868
01869
01870
01871
01872
01873
01874 wcsncpy( s1, s, MaxTagNameLength );
01875
01876
01877
01878
01879
01880
while (*s++) { NOTHING; }
01881
01882
01883
01884
01885
01886 TagEntry += 1;
01887 }
01888 }
01889 }
01890
01891 Result = TagIndex << HEAP_TAG_SHIFT;
01892
01893 } finally {
01894
01895
01896
01897
01898
01899
if (LockAcquired) {
01900
01901
RtlReleaseLockRoutine( Heap->
LockVariable );
01902 }
01903 }
01904
01905
01906
01907
01908
01909
01910
return Result;
01911 }
01912
01913
01914
01915
01916
01917
01918 PWSTR
01919 RtlQueryTagHeap (
01920 IN PVOID HeapHandle,
01921 IN ULONG Flags,
01922 IN USHORT TagIndex,
01923 IN BOOLEAN ResetCounters,
01924 OUT PRTL_HEAP_TAG_INFO TagInfo OPTIONAL
01925 )
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960 {
01961
PHEAP Heap = (
PHEAP)
HeapHandle;
01962 BOOLEAN LockAcquired =
FALSE;
01963
PHEAP_TAG_ENTRY TagEntry;
01964 PWSTR Result;
01965
01966
01967
01968
01969
01970
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
NULL );
01971
01972
01973
01974
01975
01976
if (!
IS_HEAP_TAGGING_ENABLED()) {
01977
01978
return NULL;
01979 }
01980
01981
try {
01982
01983
01984
01985
01986
01987
if (Heap !=
NULL) {
01988
01989
01990
01991
01992
01993
01994
if (
DEBUG_HEAP( Flags )) {
01995
01996 Result =
RtlDebugQueryTagHeap(
HeapHandle, Flags, TagIndex, ResetCounters, TagInfo );
01997 leave;
01998 }
01999
02000
02001
02002
02003
02004 Flags |= Heap->
ForceFlags;
02005
02006
if (!(Flags & HEAP_NO_SERIALIZE)) {
02007
02008
RtlAcquireLockRoutine( Heap->
LockVariable );
02009
02010 LockAcquired =
TRUE;
02011 }
02012 }
02013
02014 Result =
NULL;
02015
02016
02017
02018
02019
02020
02021
02022
02023
if ((TagIndex < Heap->
NextAvailableTagIndex) &&
02024 (Heap->
TagEntries !=
NULL)) {
02025
02026
02027
02028
02029
02030
02031 TagEntry = Heap->
TagEntries + TagIndex;
02032
02033
if (ARGUMENT_PRESENT( TagInfo )) {
02034
02035 TagInfo->NumberOfAllocations = TagEntry->
Allocs;
02036 TagInfo->NumberOfFrees = TagEntry->
Frees;
02037 TagInfo->BytesAllocated = TagEntry->
Size <<
HEAP_GRANULARITY_SHIFT;
02038 }
02039
02040
02041
02042
02043
02044
if (ResetCounters) {
02045
02046 TagEntry->
Allocs = 0;
02047 TagEntry->
Frees = 0;
02048 TagEntry->
Size = 0;
02049 }
02050
02051
02052
02053
02054
02055 Result = &TagEntry->
TagName[ 0 ];
02056
02057
02058
02059
02060
02061
02062
02063 }
else if (TagIndex & HEAP_PSEUDO_TAG_FLAG) {
02064
02065
02066
02067
02068
02069 TagIndex ^= HEAP_PSEUDO_TAG_FLAG;
02070
02071
if ((TagIndex <
HEAP_NUMBER_OF_PSEUDO_TAG) &&
02072 (Heap->
PseudoTagEntries !=
NULL)) {
02073
02074
02075
02076
02077
02078
02079 TagEntry = (
PHEAP_TAG_ENTRY)(Heap->
PseudoTagEntries + TagIndex);
02080
02081
if (ARGUMENT_PRESENT( TagInfo )) {
02082
02083 TagInfo->NumberOfAllocations = TagEntry->
Allocs;
02084 TagInfo->NumberOfFrees = TagEntry->
Frees;
02085 TagInfo->BytesAllocated = TagEntry->
Size <<
HEAP_GRANULARITY_SHIFT;
02086 }
02087
02088
02089
02090
02091
02092
if (ResetCounters) {
02093
02094 TagEntry->
Allocs = 0;
02095 TagEntry->
Frees = 0;
02096 TagEntry->
Size = 0;
02097 }
02098
02099
02100
02101
02102
02103 Result =
L"";
02104 }
02105 }
02106
02107 } finally {
02108
02109
02110
02111
02112
02113
if (LockAcquired) {
02114
02115
RtlReleaseLockRoutine( Heap->
LockVariable );
02116 }
02117 }
02118
02119
02120
02121
02122
02123
return Result;
02124 }
02125
02126
02127
02128
02129
02130
02131
NTSTATUS
02132 RtlExtendHeap (
02133 IN PVOID HeapHandle,
02134 IN ULONG Flags,
02135 IN PVOID Base,
02136 IN SIZE_T Size
02137 )
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167 {
02168
PHEAP Heap = (
PHEAP)
HeapHandle;
02169
NTSTATUS Status;
02170
PHEAP_SEGMENT Segment;
02171 BOOLEAN LockAcquired =
FALSE;
02172 UCHAR SegmentIndex, EmptySegmentIndex;
02173 SIZE_T CommitSize;
02174 SIZE_T ReserveSize;
02175 ULONG SegmentFlags;
02176 PVOID CommittedBase;
02177 PVOID UnCommittedBase;
02178 MEMORY_BASIC_INFORMATION MemoryInformation;
02179
02180
02181
02182
02183
02184
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
02185
RtlpDebugPageHeapExtend(
HeapHandle, Flags, Base,
Size ));
02186
02187
02188
02189
02190
02191
02192
Status =
NtQueryVirtualMemory( NtCurrentProcess(),
02193 Base,
02194 MemoryBasicInformation,
02195 &MemoryInformation,
02196
sizeof( MemoryInformation ),
02197
NULL );
02198
02199
if (!
NT_SUCCESS(
Status )) {
02200
02201
return Status;
02202 }
02203
02204
if (MemoryInformation.State == MEM_FREE) {
02205
02206
return STATUS_INVALID_PARAMETER;
02207 }
02208
02209
02210
02211
02212
02213
02214
02215
if (MemoryInformation.BaseAddress != Base) {
02216
02217 MemoryInformation.BaseAddress = (PCHAR)MemoryInformation.BaseAddress +
PAGE_SIZE;
02218 MemoryInformation.RegionSize -=
PAGE_SIZE;
02219 }
02220
02221
try {
02222
02223
02224
02225
02226
02227
if (!(Flags & HEAP_NO_SERIALIZE)) {
02228
02229
RtlAcquireLockRoutine( Heap->
LockVariable );
02230
02231 LockAcquired =
TRUE;
02232 }
02233
02234
02235
02236
02237
02238
02239
Status = STATUS_INSUFFICIENT_RESOURCES;
02240
02241 EmptySegmentIndex =
HEAP_MAXIMUM_SEGMENTS;
02242
02243
for (SegmentIndex=0; SegmentIndex<
HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) {
02244
02245 Segment = Heap->
Segments[ SegmentIndex ];
02246
02247
if (Segment) {
02248
02249
if (((ULONG_PTR)Base >= (ULONG_PTR)Segment) &&
02250 ((ULONG_PTR)Base < (ULONG_PTR)(Segment->
LastValidEntry))) {
02251
02252
Status = STATUS_INVALID_PARAMETER;
02253
02254
break;
02255 }
02256
02257 }
else if ((Segment ==
NULL) &&
02258 (EmptySegmentIndex ==
HEAP_MAXIMUM_SEGMENTS)) {
02259
02260 EmptySegmentIndex = SegmentIndex;
02261
02262
Status = STATUS_SUCCESS;
02263 }
02264 }
02265
02266
02267
02268
02269
02270
02271
02272
if (
NT_SUCCESS(
Status )) {
02273
02274
02275
02276
02277
02278 SegmentFlags =
HEAP_SEGMENT_USER_ALLOCATED;
02279
02280 CommittedBase = MemoryInformation.BaseAddress;
02281
02282
02283
02284
02285
02286
02287
02288
if (MemoryInformation.State == MEM_COMMIT) {
02289
02290 CommitSize = MemoryInformation.RegionSize;
02291
02292 UnCommittedBase = (PCHAR)CommittedBase + CommitSize;
02293
02294
Status =
NtQueryVirtualMemory( NtCurrentProcess(),
02295 UnCommittedBase,
02296 MemoryBasicInformation,
02297 &MemoryInformation,
02298
sizeof( MemoryInformation ),
02299
NULL );
02300
02301 ReserveSize = CommitSize;
02302
02303
if ((
NT_SUCCESS(
Status )) &&
02304 (MemoryInformation.State == MEM_RESERVE)) {
02305
02306 ReserveSize += MemoryInformation.RegionSize;
02307 }
02308
02309 }
else {
02310
02311
02312
02313
02314
02315
02316
02317 UnCommittedBase = CommittedBase;
02318
02319 ReserveSize = MemoryInformation.RegionSize;
02320 }
02321
02322
02323
02324
02325
02326
02327
02328
02329
if ((ReserveSize <
PAGE_SIZE) ||
02330 (
Size > ReserveSize)) {
02331
02332
Status = STATUS_BUFFER_TOO_SMALL;
02333
02334 }
else {
02335
02336
02337
02338
02339
02340
02341
if (UnCommittedBase == CommittedBase) {
02342
02343 CommitSize =
PAGE_SIZE;
02344
02345
Status = ZwAllocateVirtualMemory( NtCurrentProcess(),
02346 (PVOID *)&Segment,
02347 0,
02348 &CommitSize,
02349 MEM_COMMIT,
02350 PAGE_READWRITE );
02351 }
02352 }
02353
02354
02355
02356
02357
02358
02359
02360
if (
NT_SUCCESS(
Status )) {
02361
02362
if (
RtlpInitializeHeapSegment( Heap,
02363 Segment,
02364 EmptySegmentIndex,
02365 0,
02366 Segment,
02367 (PCHAR)Segment + CommitSize,
02368 (PCHAR)Segment + ReserveSize )) {
02369
02370
Status = STATUS_NO_MEMORY;
02371 }
02372 }
02373 }
02374
02375 } finally {
02376
02377
02378
02379
02380
02381
if (LockAcquired) {
02382
02383
RtlReleaseLockRoutine( Heap->
LockVariable );
02384 }
02385 }
02386
02387
02388
02389
02390
02391
return Status;
02392 }
02393
02394
02395
02396
02397
02398
02399 SIZE_T
02400 NTAPI
02401 RtlCompactHeap (
02402 IN PVOID HeapHandle,
02403 IN ULONG Flags
02404 )
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428 {
02429
PHEAP Heap = (
PHEAP)
HeapHandle;
02430
PHEAP_FREE_ENTRY FreeBlock;
02431
PHEAP_SEGMENT Segment;
02432 UCHAR SegmentIndex;
02433 SIZE_T LargestFreeSize;
02434 BOOLEAN LockAcquired =
FALSE;
02435
02436
02437
02438
02439
02440 Flags |= Heap->
ForceFlags;
02441
02442
02443
02444
02445
02446
if (
DEBUG_HEAP( Flags )) {
02447
02448
return RtlDebugCompactHeap(
HeapHandle, Flags );
02449 }
02450
02451
try {
02452
02453
02454
02455
02456
02457
if (!(Flags & HEAP_NO_SERIALIZE)) {
02458
02459
RtlAcquireLockRoutine( Heap->
LockVariable );
02460
02461 LockAcquired =
TRUE;
02462 }
02463
02464 LargestFreeSize = 0;
02465
02466
try {
02467
02468
02469
02470
02471
02472
02473 FreeBlock =
RtlpCoalesceHeap( (
PHEAP)
HeapHandle );
02474
02475
02476
02477
02478
02479
if (FreeBlock !=
NULL) {
02480
02481 LargestFreeSize = FreeBlock->
Size <<
HEAP_GRANULARITY_SHIFT;
02482 }
02483
02484
02485
02486
02487
02488
02489
02490
for (SegmentIndex=0; SegmentIndex<
HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) {
02491
02492 Segment = Heap->
Segments[ SegmentIndex ];
02493
02494
if (Segment && Segment->
LargestUnCommittedRange > LargestFreeSize) {
02495
02496 LargestFreeSize = Segment->
LargestUnCommittedRange;
02497 }
02498 }
02499
02500 } except(
EXCEPTION_EXECUTE_HANDLER ) {
02501
02502
SET_LAST_STATUS( GetExceptionCode() );
02503 }
02504
02505 } finally {
02506
02507
02508
02509
02510
02511
if (LockAcquired) {
02512
02513
RtlReleaseLockRoutine( Heap->
LockVariable );
02514 }
02515 }
02516
02517
02518
02519
02520
02521
return LargestFreeSize;
02522 }
02523
02524
02525
02526
02527
02528
02529 BOOLEAN
02530 RtlValidateHeap (
02531 PVOID HeapHandle,
02532 IN ULONG Flags,
02533 IN PVOID BaseAddress
02534 )
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558 {
02559
PHEAP Heap = (
PHEAP)
HeapHandle;
02560 BOOLEAN LockAcquired =
FALSE;
02561 BOOLEAN Result;
02562
02563
try {
02564
02565
try {
02566
02567
02568
02569
02570
02571
if (
IS_DEBUG_PAGE_HEAP_HANDLE(
HeapHandle )) {
02572
02573 Result =
RtlpDebugPageHeapValidate(
HeapHandle, Flags, BaseAddress );
02574
02575 }
else {
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592
PHEAP_LOOKASIDE Lookaside = (
PHEAP_LOOKASIDE)Heap->
Lookaside;
02593
02594
if (Lookaside !=
NULL) {
02595
02596 ULONG i;
02597 PVOID Block;
02598
02599 Heap->
Lookaside =
NULL;
02600
02601
for (i = 0; i <
HEAP_MAXIMUM_FREELISTS; i += 1) {
02602
02603
while ((Block =
RtlpAllocateFromHeapLookaside(&(Lookaside[i]))) !=
NULL) {
02604
02605
RtlFreeHeap(
HeapHandle, 0, Block );
02606 }
02607 }
02608 }
02609
02610 Result =
FALSE;
02611
02612
02613
02614
02615
02616
if (
RtlpCheckHeapSignature( Heap,
"RtlValidateHeap" )) {
02617
02618 Flags |= Heap->
ForceFlags;
02619
02620
02621
02622
02623
02624
if (!(Flags & HEAP_NO_SERIALIZE)) {
02625
02626
RtlAcquireLockRoutine( Heap->
LockVariable );
02627
02628 LockAcquired =
TRUE;
02629 }
02630
02631
02632
02633
02634
02635
02636
02637
if (BaseAddress ==
NULL) {
02638
02639 Result =
RtlpValidateHeap( Heap,
TRUE );
02640
02641 }
else {
02642
02643 Result =
RtlpValidateHeapEntry( Heap, (
PHEAP_ENTRY)BaseAddress - 1,
"RtlValidateHeap" );
02644 }
02645 }
02646 }
02647
02648 } except(
EXCEPTION_EXECUTE_HANDLER ) {
02649
02650
SET_LAST_STATUS( GetExceptionCode() );
02651
02652 Result =
FALSE;
02653 }
02654
02655 } finally {
02656
02657
02658
02659
02660
02661
if (LockAcquired) {
02662
02663
RtlReleaseLockRoutine( Heap->
LockVariable );
02664 }
02665 }
02666
02667
02668
02669
02670
02671
return Result;
02672 }
02673
02674
02675
02676
02677
02678
02679 BOOLEAN
02680 RtlValidateProcessHeaps (
02681 VOID
02682 )
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702 {
02703
NTSTATUS Status;
02704 ULONG i, NumberOfHeaps;
02705 PVOID HeapsArray[ 512 ];
02706 PVOID *Heaps;
02707 SIZE_T
Size;
02708 BOOLEAN Result;
02709
02710 Result =
TRUE;
02711
02712 Heaps = &HeapsArray[ 0 ];
02713
02714
02715
02716
02717
02718
02719
02720
02721 NumberOfHeaps =
RtlGetProcessHeaps( 512, Heaps );
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
if (NumberOfHeaps > 512) {
02733
02734
02735
02736
02737
02738
02739
02740 Heaps =
NULL;
02741
Size = NumberOfHeaps *
sizeof( PVOID );
02742
02743
Status = ZwAllocateVirtualMemory( NtCurrentProcess(),
02744 (PVOID *)&Heaps,
02745 0,
02746 &
Size,
02747 MEM_COMMIT,
02748 PAGE_READWRITE );
02749
02750
if (!
NT_SUCCESS(
Status )) {
02751
02752
return FALSE;
02753 }
02754
02755
02756
02757
02758
02759
02760
02761 NumberOfHeaps =
RtlGetProcessHeaps( 512, Heaps );
02762 }
02763
02764
02765
02766
02767
02768
02769
for (i=0; i<NumberOfHeaps; i++) {
02770
02771
if (!
RtlValidateHeap( Heaps[i], 0,
NULL )) {
02772
02773 Result =
FALSE;
02774 }
02775 }
02776
02777
02778
02779
02780
02781
02782
if (Heaps != &HeapsArray[ 0 ]) {
02783
02784 ZwFreeVirtualMemory( NtCurrentProcess(),
02785 (PVOID *)&Heaps,
02786 &
Size,
02787 MEM_RELEASE );
02788 }
02789
02790
02791
02792
02793
02794
return Result;
02795 }
02796
02797
02798
02799
02800
02801
02802 ULONG
02803 RtlGetProcessHeaps (
02804 ULONG NumberOfHeapsToReturn,
02805 PVOID *ProcessHeaps
02806 )
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831 {
02832 PPEB Peb = NtCurrentPeb();
02833 ULONG NumberOfHeapsToCopy;
02834 ULONG TotalHeaps;
02835
02836
RtlAcquireLockRoutine( &
RtlpProcessHeapsListLock.
Lock );
02837
02838
try {
02839
02840
02841
02842
02843
02844 TotalHeaps = Peb->NumberOfHeaps;
02845
02846
if (TotalHeaps > NumberOfHeapsToReturn) {
02847
02848 NumberOfHeapsToCopy = NumberOfHeapsToReturn;
02849
02850 }
else {
02851
02852 NumberOfHeapsToCopy = TotalHeaps;
02853
02854 }
02855
02856
02857
02858
02859
02860 RtlMoveMemory( ProcessHeaps,
02861 Peb->ProcessHeaps,
02862 NumberOfHeapsToCopy *
sizeof( *ProcessHeaps ));
02863
02864 ProcessHeaps += NumberOfHeapsToCopy;
02865 NumberOfHeapsToReturn -= NumberOfHeapsToCopy;
02866
02867 } finally {
02868
02869
RtlReleaseLockRoutine( &
RtlpProcessHeapsListLock.
Lock );
02870 }
02871
02872
#ifdef DEBUG_PAGE_HEAP
02873
02874
02875
02876
02877
02878
if (
RtlpDebugPageHeap ) {
02879
02880 TotalHeaps +=
02881
RtlpDebugPageHeapGetProcessHeaps( NumberOfHeapsToReturn, ProcessHeaps );
02882
02883 }
02884
02885
#endif
02886
02887
return TotalHeaps;
02888 }
02889
02890
02891
02892
02893
02894
02895
NTSTATUS
02896 RtlEnumProcessHeaps (
02897 PRTL_ENUM_HEAPS_ROUTINE EnumRoutine,
02898 PVOID Parameter
02899 )
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923 {
02924 PPEB Peb = NtCurrentPeb();
02925
NTSTATUS Status;
02926 ULONG i;
02927
02928
Status = STATUS_SUCCESS;
02929
02930
02931
02932
02933
02934
RtlAcquireLockRoutine( &
RtlpProcessHeapsListLock.
Lock );
02935
02936
try {
02937
02938
02939
02940
02941
02942
02943
02944
for (i=0; i<Peb->NumberOfHeaps; i++) {
02945
02946
Status = (*EnumRoutine)( (
PHEAP)(Peb->ProcessHeaps[ i ]), Parameter );
02947
02948
if (!
NT_SUCCESS(
Status )) {
02949
02950
break;
02951 }
02952 }
02953
02954 } finally {
02955
02956
02957
02958
02959
02960
RtlReleaseLockRoutine( &
RtlpProcessHeapsListLock.
Lock );
02961 }
02962
02963
02964
02965
02966
02967
return Status;
02968 }
02969
02970
02971
02972
02973
02974
02975
NTSTATUS
02976 RtlUsageHeap (
02977 IN PVOID HeapHandle,
02978 IN ULONG Flags,
02979 IN OUT PRTL_HEAP_USAGE Usage
02980 )
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016 {
03017
NTSTATUS Status;
03018
PHEAP Heap = (
PHEAP)
HeapHandle;
03019
PRTL_HEAP_USAGE_INTERNAL Buffer;
03020
PHEAP_SEGMENT Segment;
03021
PHEAP_UNCOMMMTTED_RANGE UnCommittedRange;
03022
PHEAP_ENTRY CurrentBlock;
03023
PHEAP_ENTRY_EXTRA ExtraStuff;
03024 PLIST_ENTRY Head, Next;
03025
PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock;
03026 SIZE_T BytesFree;
03027 UCHAR SegmentIndex;
03028 BOOLEAN LockAcquired =
FALSE;
03029 BOOLEAN VirtualAllocBlockSeen;
03030 PRTL_HEAP_USAGE_ENTRY pOldEntries, pNewEntries, pNewEntry;
03031 PRTL_HEAP_USAGE_ENTRY *ppEntries, *ppAddedEntries, *ppRemovedEntries, *pp;
03032 PVOID DataAddress;
03033 SIZE_T DataSize;
03034
03035
03036
03037
03038
03039 Flags |= Heap->
ForceFlags;
03040
03041
03042
03043
03044
03045
if (
DEBUG_HEAP( Flags )) {
03046
03047
return RtlDebugUsageHeap(
HeapHandle, Flags,
Usage );
03048 }
03049
03050
03051
03052
03053
03054
if (
Usage->Length !=
sizeof( RTL_HEAP_USAGE )) {
03055
03056
return STATUS_INFO_LENGTH_MISMATCH;
03057 }
03058
03059
03060
03061
03062
03063
Usage->BytesAllocated = 0;
03064
Usage->BytesCommitted = 0;
03065
Usage->BytesReserved = 0;
03066
Usage->BytesReservedMaximum = 0;
03067
03068
03069
03070
03071
03072
03073
Buffer = (
PRTL_HEAP_USAGE_INTERNAL)&
Usage->Reserved[ 0 ];
03074
03075
03076
03077
03078
03079
03080
if ((
Buffer->Base ==
NULL) &&
03081 (Flags & HEAP_USAGE_ALLOCATED_BLOCKS)) {
03082
03083
Buffer->ReservedSize = 4 * 1024 * 1024;
03084
03085
Status =
NtAllocateVirtualMemory( NtCurrentProcess(),
03086 &
Buffer->Base,
03087 0,
03088 &
Buffer->ReservedSize,
03089 MEM_RESERVE,
03090 PAGE_READWRITE );
03091
03092
if (!
NT_SUCCESS(
Status )) {
03093
03094
return Status;
03095 }
03096
03097
Buffer->CommittedSize = 0;
03098
Buffer->FreeList =
NULL;
03099
Buffer->LargeEntriesSentinal =
NULL;
03100
03101
03102
03103
03104
03105
03106 }
else if ((
Buffer->Base !=
NULL) &&
03107 (Flags & HEAP_USAGE_FREE_BUFFER)) {
03108
03109
Buffer->ReservedSize = 0;
03110
03111
Status =
NtFreeVirtualMemory( NtCurrentProcess(),
03112 &
Buffer->Base,
03113 &
Buffer->ReservedSize,
03114 MEM_RELEASE );
03115
03116
if (!
NT_SUCCESS(
Status )) {
03117
03118
return Status;
03119 }
03120
03121 RtlZeroMemory(
Buffer,
sizeof( *
Buffer ) );
03122 }
03123
03124
03125
03126
03127
03128 Flags |= Heap->
ForceFlags;
03129
03130
try {
03131
03132
03133
03134
03135
03136
if (!(Flags & HEAP_NO_SERIALIZE)) {
03137
03138
RtlAcquireLockRoutine( Heap->
LockVariable );
03139
03140 LockAcquired =
TRUE;
03141 }
03142
03143
03144
03145
03146
03147
03148
03149
03150
for (SegmentIndex=0; SegmentIndex<
HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) {
03151
03152 Segment = Heap->
Segments[ SegmentIndex ];
03153
03154
if (Segment) {
03155
03156
Usage->BytesCommitted += (Segment->
NumberOfPages -
03157 Segment->
NumberOfUnCommittedPages) *
PAGE_SIZE;
03158
03159
Usage->BytesReserved += Segment->
NumberOfPages *
PAGE_SIZE;
03160
03161 }
else if (Heap->
Flags & HEAP_GROWABLE) {
03162
03163
Usage->BytesReservedMaximum += Heap->
SegmentReserve;
03164 }
03165 }
03166
03167
Usage->BytesReservedMaximum +=
Usage->BytesReserved;
03168
Usage->BytesAllocated =
Usage->BytesCommitted - (Heap->
TotalFreeSize <<
HEAP_GRANULARITY_SHIFT);
03169
03170
03171
03172
03173
03174
03175 Head = &Heap->
VirtualAllocdBlocks;
03176 Next = Head->Flink;
03177
03178
while (Head != Next) {
03179
03180 VirtualAllocBlock = CONTAINING_RECORD( Next,
HEAP_VIRTUAL_ALLOC_ENTRY, Entry );
03181
03182
Usage->BytesAllocated += VirtualAllocBlock->
CommitSize;
03183
Usage->BytesCommitted += VirtualAllocBlock->
CommitSize;
03184
03185 Next = Next->Flink;
03186 }
03187
03188
Status = STATUS_SUCCESS;
03189
03190
03191
03192
03193
03194
03195
if ((
Buffer->Base !=
NULL) &&
03196 (Flags & HEAP_USAGE_ALLOCATED_BLOCKS)) {
03197
03198
03199
03200
03201
03202
03203
03204 pOldEntries =
Usage->Entries;
03205
03206 ppEntries = &
Usage->Entries;
03207
03208 *ppEntries =
NULL;
03209
03210 ppAddedEntries = &
Usage->AddedEntries;
03211
03212
while (*ppAddedEntries =
RtlpFreeHeapUsageEntry(
Buffer, *ppAddedEntries )) { NOTHING; }
03213
03214 ppRemovedEntries = &
Usage->RemovedEntries;
03215
03216
while (*ppRemovedEntries =
RtlpFreeHeapUsageEntry(
Buffer, *ppRemovedEntries )) { NOTHING; }
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
for (SegmentIndex=0; SegmentIndex<
HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) {
03229
03230 Segment = Heap->
Segments[ SegmentIndex ];
03231
03232
03233
03234
03235
03236
if (Segment) {
03237
03238
03239
03240
03241
03242
03243
03244
if (Segment->
BaseAddress == Heap) {
03245
03246 CurrentBlock = &Heap->
Entry;
03247
03248 }
else {
03249
03250 CurrentBlock = &Segment->
Entry;
03251 }
03252
03253
03254
03255
03256
03257
03258
03259
while (CurrentBlock < Segment->
LastValidEntry) {
03260
03261
if (CurrentBlock->
Flags &
HEAP_ENTRY_BUSY) {
03262
03263
03264
03265
03266
03267 DataAddress = (CurrentBlock+1);
03268 DataSize = (CurrentBlock->
Size <<
HEAP_GRANULARITY_SHIFT) -
03269 CurrentBlock->
UnusedBytes;
03270
03271 keepLookingAtOldEntries:
03272
03273
03274
03275
03276
03277
03278
03279
if (pOldEntries ==
Buffer->LargeEntriesSentinal) {
03280
03281
goto keepLookingAtNewEntries;
03282 }
03283
03284
03285
03286
03287
03288
03289
03290
03291
03292
if ((pOldEntries->Address == DataAddress) &&
03293 (pOldEntries->Size == DataSize)) {
03294
03295
03296
03297
03298
03299 *ppEntries = pOldEntries;
03300 pOldEntries = pOldEntries->Next;
03301 ppEntries = &(*ppEntries)->Next;
03302
03303 *ppEntries =
NULL;
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314 }
else if (pOldEntries->Address <= DataAddress) {
03315
03316 *ppRemovedEntries = pOldEntries;
03317 pOldEntries = pOldEntries->Next;
03318 ppRemovedEntries = &(*ppRemovedEntries)->Next;
03319
03320 *ppRemovedEntries =
NULL;
03321
03322
goto keepLookingAtOldEntries;
03323
03324
03325
03326
03327
03328 }
else {
03329
03330 keepLookingAtNewEntries:
03331
03332
03333
03334
03335
03336 pNewEntry =
NULL;
03337
03338
Status =
RtlpAllocateHeapUsageEntry(
Buffer, &pNewEntry );
03339
03340
if (!
NT_SUCCESS(
Status )) {
03341
03342
break;
03343 }
03344
03345
03346
03347
03348
03349 pNewEntry->Address = DataAddress;
03350 pNewEntry->Size = DataSize;
03351
03352
03353
03354
03355
03356
03357
if (CurrentBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
03358
03359 ExtraStuff =
RtlpGetExtraStuffPointer( CurrentBlock );
03360
03361
#if i386
03362
03363 pNewEntry->AllocatorBackTraceIndex = ExtraStuff->
AllocatorBackTraceIndex;
03364
03365
#endif // i386
03366
03367
if (!
IS_HEAP_TAGGING_ENABLED()) {
03368
03369 pNewEntry->TagIndex = 0;
03370
03371 }
else {
03372
03373 pNewEntry->TagIndex = ExtraStuff->
TagIndex;
03374 }
03375
03376 }
else {
03377
03378
03379
03380
03381
03382
03383
#if i386
03384
03385 pNewEntry->AllocatorBackTraceIndex = 0;
03386
03387
#endif // i386
03388
03389
if (!
IS_HEAP_TAGGING_ENABLED()) {
03390
03391 pNewEntry->TagIndex = 0;
03392
03393 }
else {
03394
03395 pNewEntry->TagIndex = CurrentBlock->
SmallTagIndex;
03396 }
03397 }
03398
03399
03400
03401
03402
03403
03404
Status =
RtlpAllocateHeapUsageEntry(
Buffer, ppAddedEntries );
03405
03406
if (!
NT_SUCCESS(
Status )) {
03407
03408
break;
03409 }
03410
03411
03412
03413
03414
03415 **ppAddedEntries = *pNewEntry;
03416
03417
03418
03419
03420
03421 ppAddedEntries = &((*ppAddedEntries)->Next);
03422
03423 *ppAddedEntries =
NULL;
03424
03425 pNewEntry->Next =
NULL;
03426
03427
03428
03429
03430
03431 *ppEntries = pNewEntry;
03432 ppEntries = &pNewEntry->Next;
03433 }
03434 }
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
if (CurrentBlock->
Flags &
HEAP_ENTRY_LAST_ENTRY) {
03445
03446 CurrentBlock += CurrentBlock->
Size;
03447
03448
if (CurrentBlock < Segment->
LastValidEntry) {
03449
03450 UnCommittedRange = Segment->
UnCommittedRanges;
03451
03452
while ((UnCommittedRange !=
NULL) &&
03453 (UnCommittedRange->
Address != (ULONG_PTR)CurrentBlock)) {
03454
03455 UnCommittedRange = UnCommittedRange->
Next;
03456 }
03457
03458
if (UnCommittedRange ==
NULL) {
03459
03460 CurrentBlock = Segment->
LastValidEntry;
03461
03462 }
else {
03463
03464 CurrentBlock = (
PHEAP_ENTRY)(UnCommittedRange->
Address +
03465 UnCommittedRange->
Size);
03466 }
03467 }
03468
03469 }
else {
03470
03471
03472
03473
03474
03475
03476 CurrentBlock += CurrentBlock->
Size;
03477 }
03478 }
03479 }
03480 }
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490
03491
03492
03493
03494
if (
NT_SUCCESS(
Status )) {
03495
03496
03497
03498
03499
03500
03501 Head = &Heap->
VirtualAllocdBlocks;
03502 Next = Head->Flink;
03503 VirtualAllocBlockSeen =
FALSE;
03504
03505
while (Head != Next) {
03506
03507 VirtualAllocBlock = CONTAINING_RECORD( Next,
HEAP_VIRTUAL_ALLOC_ENTRY, Entry );
03508
03509
03510
03511
03512
03513 pNewEntry =
NULL;
03514
03515
Status =
RtlpAllocateHeapUsageEntry(
Buffer, &pNewEntry );
03516
03517
if (!
NT_SUCCESS(
Status )) {
03518
03519
break;
03520 }
03521
03522 VirtualAllocBlockSeen =
TRUE;
03523
03524
03525
03526
03527
03528 pNewEntry->Address = (VirtualAllocBlock + 1);
03529 pNewEntry->Size = VirtualAllocBlock->
CommitSize - VirtualAllocBlock->
BusyBlock.
Size;
03530
03531
#if i386
03532
03533 pNewEntry->AllocatorBackTraceIndex = VirtualAllocBlock->
ExtraStuff.
AllocatorBackTraceIndex;
03534
03535
#endif // i386
03536
03537
if (!
IS_HEAP_TAGGING_ENABLED()) {
03538
03539 pNewEntry->TagIndex = 0;
03540
03541 }
else {
03542
03543 pNewEntry->TagIndex = VirtualAllocBlock->
ExtraStuff.
TagIndex;
03544 }
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560 pp = ppEntries;
03561
03562
while (*pp) {
03563
03564
if ((*pp)->Address >= pNewEntry->Address) {
03565
03566
break;
03567 }
03568
03569 pp = &(*pp)->Next;
03570 }
03571
03572 pNewEntry->Next = *pp;
03573 *pp = pNewEntry;
03574
03575
03576
03577
03578
03579 Next = Next->Flink;
03580 }
03581
03582
03583
03584
03585
03586
03587
03588
03589
03590
if (
NT_SUCCESS(
Status )) {
03591
03592 pOldEntries =
Buffer->LargeEntriesSentinal;
03593
Buffer->LargeEntriesSentinal = *ppEntries;
03594
03595
03596
03597
03598
03599
03600
03601
while (pOldEntries !=
NULL) {
03602
03603
03604
03605
03606
03607
03608
03609
03610
if ((*ppEntries !=
NULL) &&
03611 (pOldEntries->Address == (*ppEntries)->Address) &&
03612 (pOldEntries->Size == (*ppEntries)->Size)) {
03613
03614 ppEntries = &(*ppEntries)->Next;
03615
03616 pOldEntries =
RtlpFreeHeapUsageEntry(
Buffer, pOldEntries );
03617
03618
03619
03620
03621
03622
03623
03624 }
else if ((*ppEntries ==
NULL) ||
03625 (pOldEntries->Address < (*ppEntries)->Address)) {
03626
03627 *ppRemovedEntries = pOldEntries;
03628
03629 pOldEntries = pOldEntries->Next;
03630
03631 ppRemovedEntries = &(*ppRemovedEntries)->Next;
03632
03633 *ppRemovedEntries =
NULL;
03634
03635
03636
03637
03638
03639
03640 }
else {
03641
03642 *ppAddedEntries = pOldEntries;
03643
03644 pOldEntries = pOldEntries->Next;
03645
03646 **ppAddedEntries = **ppEntries;
03647
03648 ppAddedEntries = &(*ppAddedEntries)->Next;
03649
03650 *ppAddedEntries =
NULL;
03651 }
03652 }
03653
03654
03655
03656
03657
03658
while (pNewEntry = *ppEntries) {
03659
03660
Status =
RtlpAllocateHeapUsageEntry(
Buffer, ppAddedEntries );
03661
03662
if (!
NT_SUCCESS(
Status )) {
03663
03664
break;
03665 }
03666
03667 **ppAddedEntries = *pNewEntry;
03668
03669 ppAddedEntries = &(*ppAddedEntries)->Next;
03670
03671 *ppAddedEntries =
NULL;
03672
03673 ppEntries = &pNewEntry->Next;
03674 }
03675
03676
03677
03678
03679
03680
03681
if ((
Usage->AddedEntries !=
NULL) || (
Usage->RemovedEntries !=
NULL)) {
03682
03683
Status = STATUS_MORE_ENTRIES;
03684 }
03685 }
03686 }
03687 }
03688
03689 } finally {
03690
03691
03692
03693
03694
03695
if (LockAcquired) {
03696
03697
RtlReleaseLockRoutine( Heap->
LockVariable );
03698 }
03699 }
03700
03701
03702
03703
03704
03705
return Status;
03706 }
03707
03708
03709
03710
03711
03712
03713
NTSTATUS
03714 RtlWalkHeap (
03715 IN PVOID HeapHandle,
03716 IN OUT PRTL_HEAP_WALK_ENTRY Entry
03717 )
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732
03733
03734
03735
03736
03737
03738
03739
03740 {
03741
NTSTATUS Status;
03742
PHEAP Heap = (
PHEAP)
HeapHandle;
03743
PHEAP_SEGMENT Segment;
03744 UCHAR SegmentIndex;
03745
PHEAP_ENTRY CurrentBlock;
03746
PHEAP_ENTRY_EXTRA ExtraStuff;
03747
PHEAP_UNCOMMMTTED_RANGE UnCommittedRange, *pp;
03748 PLIST_ENTRY Next, Head;
03749
PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock;
03750
03751
03752
03753
03754
03755
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
03756
RtlpDebugPageHeapWalk(
HeapHandle, Entry ));
03757
03758
03759
03760
03761
03762
03763
if (
DEBUG_HEAP( Heap->
Flags )) {
03764
03765
if (!
RtlDebugWalkHeap(
HeapHandle, Entry )) {
03766
03767
return STATUS_INVALID_PARAMETER;
03768 }
03769 }
03770
03771
Status = STATUS_SUCCESS;
03772
03773
03774
03775
03776
03777
03778
03779
03780
03781
03782
03783
03784
03785
03786
03787
03788 {
03789
PHEAP_LOOKASIDE Lookaside = (
PHEAP_LOOKASIDE)Heap->
Lookaside;
03790
03791
if (Lookaside !=
NULL) {
03792
03793 ULONG i;
03794 PVOID Block;
03795
03796 Heap->
Lookaside =
NULL;
03797
03798
for (i = 0; i <
HEAP_MAXIMUM_FREELISTS; i += 1) {
03799
03800
while ((Block =
RtlpAllocateFromHeapLookaside(&(Lookaside[i]))) !=
NULL) {
03801
03802
RtlFreeHeap(
HeapHandle, 0, Block );
03803 }
03804 }
03805 }
03806 }
03807
03808
03809
03810
03811
03812
if (Entry->DataAddress ==
NULL) {
03813
03814
03815
03816
03817
03818 SegmentIndex = 0;
03819
03820 nextSegment:
03821
03822 CurrentBlock =
NULL;
03823
03824
03825
03826
03827
03828 Segment =
NULL;
03829
03830
while ((SegmentIndex <
HEAP_MAXIMUM_SEGMENTS) &&
03831 ((Segment = Heap->
Segments[ SegmentIndex ]) ==
NULL)) {
03832
03833 SegmentIndex += 1;
03834 }
03835
03836
03837
03838
03839
03840
03841
if (Segment ==
NULL) {
03842
03843 Head = &Heap->
VirtualAllocdBlocks;
03844 Next = Head->Flink;
03845
03846
if (Next == Head) {
03847
03848
Status = STATUS_NO_MORE_ENTRIES;
03849
03850 }
else {
03851
03852 VirtualAllocBlock = CONTAINING_RECORD( Next,
HEAP_VIRTUAL_ALLOC_ENTRY, Entry );
03853
03854 CurrentBlock = &VirtualAllocBlock->
BusyBlock;
03855 }
03856
03857
03858
03859
03860
03861
03862
03863
03864 }
else {
03865
03866 Entry->DataAddress = Segment;
03867
03868 Entry->DataSize = 0;
03869
03870 Entry->OverheadBytes =
sizeof( *Segment );
03871
03872 Entry->
Flags = RTL_HEAP_SEGMENT;
03873
03874 Entry->SegmentIndex = SegmentIndex;
03875
03876 Entry->Segment.CommittedSize = (Segment->
NumberOfPages -
03877 Segment->
NumberOfUnCommittedPages) *
PAGE_SIZE;
03878
03879 Entry->Segment.UnCommittedSize = Segment->
NumberOfUnCommittedPages *
PAGE_SIZE;
03880
03881 Entry->Segment.FirstEntry = (Segment->
FirstEntry->
Flags &
HEAP_ENTRY_BUSY) ?
03882 ((
PHEAP_ENTRY)Segment->
FirstEntry + 1) :
03883 (
PHEAP_ENTRY)((
PHEAP_FREE_ENTRY)Segment->
FirstEntry + 1);
03884
03885 Entry->Segment.LastEntry = Segment->
LastValidEntry;
03886 }
03887
03888
03889
03890
03891
03892
03893 }
else if (Entry->Flags & (RTL_HEAP_SEGMENT | RTL_HEAP_UNCOMMITTED_RANGE)) {
03894
03895
03896
03897
03898
03899
if ((SegmentIndex = Entry->SegmentIndex) >=
HEAP_MAXIMUM_SEGMENTS) {
03900
03901
Status = STATUS_INVALID_ADDRESS;
03902
03903 CurrentBlock =
NULL;
03904
03905 }
else {
03906
03907
03908
03909
03910
03911 Segment = Heap->
Segments[ SegmentIndex ];
03912
03913
if (Segment ==
NULL) {
03914
03915
Status = STATUS_INVALID_ADDRESS;
03916
03917 CurrentBlock =
NULL;
03918
03919
03920
03921
03922
03923
03924
03925 }
else if (Entry->Flags & RTL_HEAP_SEGMENT) {
03926
03927 CurrentBlock = (
PHEAP_ENTRY)Segment->
FirstEntry;
03928
03929
03930
03931
03932
03933
03934 }
else {
03935
03936 CurrentBlock = (
PHEAP_ENTRY)((PCHAR)Entry->DataAddress + Entry->DataSize);
03937
03938
03939
03940
03941
03942
03943
if (CurrentBlock >= Segment->
LastValidEntry) {
03944
03945 SegmentIndex += 1;
03946
03947
goto nextSegment;
03948 }
03949 }
03950 }
03951
03952
03953
03954
03955
03956
03957 }
else {
03958
03959
03960
03961
03962
03963
if (Entry->Flags &
HEAP_ENTRY_BUSY) {
03964
03965
03966
03967
03968
03969 CurrentBlock = ((
PHEAP_ENTRY)Entry->DataAddress - 1);
03970
03971
03972
03973
03974
03975
03976
03977
if (CurrentBlock->
Flags &
HEAP_ENTRY_VIRTUAL_ALLOC) {
03978
03979 Head = &Heap->
VirtualAllocdBlocks;
03980
03981 VirtualAllocBlock = CONTAINING_RECORD( CurrentBlock,
HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock );
03982
03983 Next = VirtualAllocBlock->
Entry.Flink;
03984
03985
if (Next == Head) {
03986
03987
Status = STATUS_NO_MORE_ENTRIES;
03988
03989 }
else {
03990
03991 VirtualAllocBlock = CONTAINING_RECORD( Next,
HEAP_VIRTUAL_ALLOC_ENTRY, Entry );
03992
03993 CurrentBlock = &VirtualAllocBlock->
BusyBlock;
03994 }
03995
03996
03997
03998
03999
04000 }
else {
04001
04002
04003
04004
04005
04006
04007
04008
04009 Segment = Heap->
Segments[ SegmentIndex = CurrentBlock->
SegmentIndex ];
04010
04011
if (Segment ==
NULL) {
04012
04013
Status = STATUS_INVALID_ADDRESS;
04014
04015 CurrentBlock =
NULL;
04016
04017
04018
04019
04020
04021
04022 }
else if (CurrentBlock->
Flags &
HEAP_ENTRY_LAST_ENTRY) {
04023
04024 findUncommittedRange:
04025
04026
04027
04028
04029
04030
04031 CurrentBlock += CurrentBlock->
Size;
04032
04033
if (CurrentBlock >= Segment->
LastValidEntry) {
04034
04035 SegmentIndex += 1;
04036
04037
goto nextSegment;
04038 }
04039
04040
04041
04042
04043
04044
04045 pp = &Segment->
UnCommittedRanges;
04046
04047
while ((UnCommittedRange = *pp) && UnCommittedRange->
Address != (ULONG_PTR)CurrentBlock ) {
04048
04049 pp = &UnCommittedRange->
Next;
04050 }
04051
04052
if (UnCommittedRange ==
NULL) {
04053
04054
Status = STATUS_INVALID_PARAMETER;
04055
04056 }
else {
04057
04058
04059
04060
04061
04062
04063 Entry->DataAddress = (PVOID)UnCommittedRange->
Address;
04064
04065 Entry->DataSize = UnCommittedRange->
Size;
04066
04067 Entry->OverheadBytes = 0;
04068
04069 Entry->SegmentIndex = SegmentIndex;
04070
04071 Entry->Flags = RTL_HEAP_UNCOMMITTED_RANGE;
04072 }
04073
04074
04075
04076
04077
04078
04079 CurrentBlock =
NULL;
04080
04081 }
else {
04082
04083
04084
04085
04086
04087
04088 CurrentBlock += CurrentBlock->
Size;
04089 }
04090 }
04091
04092
04093
04094
04095
04096 }
else {
04097
04098
04099
04100
04101
04102 CurrentBlock = (
PHEAP_ENTRY)((
PHEAP_FREE_ENTRY)Entry->DataAddress - 1);
04103
04104
04105
04106
04107
04108
04109
04110
04111 Segment = Heap->
Segments[ SegmentIndex = CurrentBlock->
SegmentIndex ];
04112
04113
if (Segment ==
NULL) {
04114
04115
Status = STATUS_INVALID_ADDRESS;
04116
04117 CurrentBlock =
NULL;
04118
04119
04120
04121
04122
04123
04124 }
else if (CurrentBlock->
Flags &
HEAP_ENTRY_LAST_ENTRY) {
04125
04126
goto findUncommittedRange;
04127
04128
04129
04130
04131
04132 }
else {
04133
04134 CurrentBlock += CurrentBlock->
Size;
04135 }
04136 }
04137 }
04138
04139
04140
04141
04142
04143
04144
04145
04146
if (CurrentBlock !=
NULL) {
04147
04148
04149
04150
04151
04152
if (CurrentBlock->
Flags &
HEAP_ENTRY_BUSY) {
04153
04154
04155
04156
04157
04158 Entry->DataAddress = (CurrentBlock+1);
04159
04160
if (CurrentBlock->
Flags &
HEAP_ENTRY_VIRTUAL_ALLOC) {
04161
04162 Entry->DataSize =
RtlpGetSizeOfBigBlock( CurrentBlock );
04163
04164 Entry->OverheadBytes = (UCHAR)(
sizeof( *VirtualAllocBlock ) + CurrentBlock->
Size);
04165
04166 Entry->SegmentIndex =
HEAP_MAXIMUM_SEGMENTS;
04167
04168 Entry->Flags = RTL_HEAP_BUSY |
HEAP_ENTRY_VIRTUAL_ALLOC;
04169
04170 }
else {
04171
04172 Entry->DataSize = (CurrentBlock->
Size <<
HEAP_GRANULARITY_SHIFT) -
04173 CurrentBlock->
UnusedBytes;
04174
04175 Entry->OverheadBytes = CurrentBlock->
UnusedBytes;
04176
04177 Entry->SegmentIndex = CurrentBlock->
SegmentIndex;
04178
04179 Entry->Flags = RTL_HEAP_BUSY;
04180 }
04181
04182
if (CurrentBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
04183
04184 ExtraStuff =
RtlpGetExtraStuffPointer( CurrentBlock );
04185
04186 Entry->Block.Settable = ExtraStuff->
Settable;
04187
#if i386
04188
04189 Entry->Block.AllocatorBackTraceIndex = ExtraStuff->
AllocatorBackTraceIndex;
04190
04191
#endif // i386
04192
04193
if (!
IS_HEAP_TAGGING_ENABLED()) {
04194
04195 Entry->Block.TagIndex = 0;
04196
04197 }
else {
04198
04199 Entry->Block.TagIndex = ExtraStuff->
TagIndex;
04200 }
04201
04202 Entry->Flags |= RTL_HEAP_SETTABLE_VALUE;
04203
04204 }
else {
04205
04206
if (!
IS_HEAP_TAGGING_ENABLED()) {
04207
04208 Entry->Block.TagIndex = 0;
04209
04210 }
else {
04211
04212 Entry->Block.TagIndex = CurrentBlock->
SmallTagIndex;
04213 }
04214 }
04215
04216 Entry->Flags |= CurrentBlock->
Flags &
HEAP_ENTRY_SETTABLE_FLAGS;
04217
04218
04219
04220
04221
04222 }
else {
04223
04224 Entry->DataAddress = ((
PHEAP_FREE_ENTRY)CurrentBlock+1);
04225
04226 Entry->DataSize = (CurrentBlock->
Size <<
HEAP_GRANULARITY_SHIFT) -
04227
sizeof(
HEAP_FREE_ENTRY );
04228
04229 Entry->OverheadBytes =
sizeof(
HEAP_FREE_ENTRY );
04230
04231 Entry->SegmentIndex = CurrentBlock->
SegmentIndex;
04232
04233 Entry->Flags = 0;
04234 }
04235 }
04236
04237
04238
04239
04240
04241
return Status;
04242 }
04243
04244
04245
04246
04247
04248
04249 BOOLEAN
04250 RtlpCheckHeapSignature (
04251 IN
PHEAP Heap,
04252 IN PCHAR Caller
04253 )
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274 {
04275
04276
04277
04278
04279
04280
if (Heap->Signature ==
HEAP_SIGNATURE) {
04281
04282
return TRUE;
04283
04284 }
else {
04285
04286
04287
04288
04289
04290
04291
HeapDebugPrint((
"Invalid heap signature for heap at %x", Heap ));
04292
04293
if (Caller !=
NULL) {
04294
04295
DbgPrint(
", passed to %s", Caller );
04296 }
04297
04298
DbgPrint(
"\n" );
04299
04300
HeapDebugBreak( &Heap->Signature );
04301
04302
return FALSE;
04303 }
04304 }
04305
04306
04307
04308
04309
04310
04311
PHEAP_FREE_ENTRY
04312 RtlpCoalesceHeap (
04313 IN
PHEAP Heap
04314 )
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329
04330
04331
04332
04333 {
04334 SIZE_T OldFreeSize;
04335 SIZE_T FreeSize;
04336 ULONG
n;
04337
PHEAP_FREE_ENTRY FreeBlock, LargestFreeBlock;
04338 PLIST_ENTRY FreeListHead, Next;
04339
04340
RTL_PAGED_CODE();
04341
04342 LargestFreeBlock =
NULL;
04343
04344
04345
04346
04347
04348
04349
04350 FreeListHead = &Heap->FreeLists[ 1 ];
04351
04352
n =
HEAP_MAXIMUM_FREELISTS;
04353
04354
while (
n--) {
04355
04356
04357
04358
04359
04360 Next = FreeListHead->Blink;
04361
04362
while (FreeListHead != Next) {
04363
04364
04365
04366
04367
04368
04369 FreeBlock = CONTAINING_RECORD( Next,
HEAP_FREE_ENTRY, FreeList );
04370
04371 Next = Next->Flink;
04372 OldFreeSize = FreeSize = FreeBlock->
Size;
04373
04374
04375
04376
04377
04378 FreeBlock =
RtlpCoalesceFreeBlocks( Heap,
04379 FreeBlock,
04380 &FreeSize,
04381
TRUE );
04382
04383
04384
04385
04386
04387
04388
04389
if (FreeSize != OldFreeSize) {
04390
04391
04392
04393
04394
04395
04396
04397
04398
04399
if (FreeBlock->
Size >= (
PAGE_SIZE >>
HEAP_GRANULARITY_SHIFT)
04400
04401 &&
04402
04403 (FreeBlock->
PreviousSize == 0 ||
04404 (FreeBlock->
Flags &
HEAP_ENTRY_LAST_ENTRY))) {
04405
04406
RtlpDeCommitFreeBlock( Heap, FreeBlock, FreeSize );
04407
04408 }
else {
04409
04410
RtlpInsertFreeBlock( Heap, FreeBlock, FreeSize );
04411 }
04412
04413 Next = FreeListHead->Blink;
04414
04415 }
else {
04416
04417
04418
04419
04420
04421
if ((LargestFreeBlock ==
NULL) ||
04422 (LargestFreeBlock->
Size < FreeBlock->
Size)) {
04423
04424 LargestFreeBlock = FreeBlock;
04425 }
04426 }
04427 }
04428
04429
04430
04431
04432
04433
04434
if (
n == 1) {
04435
04436 FreeListHead = &Heap->FreeLists[ 0 ];
04437
04438 }
else {
04439
04440 FreeListHead++;
04441 }
04442 }
04443
04444
04445
04446
04447
04448
return LargestFreeBlock;
04449 }
04450
04451
04452
04453
04454
04455
04456
VOID
04457 RtlpAddHeapToProcessList (
04458 IN
PHEAP Heap
04459 )
04460
04461
04462
04463
04464
04465
04466
04467
04468
04469
04470
04471
04472
04473
04474
04475
04476
04477
04478 {
04479 PPEB Peb = NtCurrentPeb();
04480
PHEAP *NewList;
04481
04482
04483
04484
04485
04486
RtlAcquireLockRoutine( &
RtlpProcessHeapsListLock.
Lock );
04487
04488
try {
04489
04490
04491
04492
04493
04494
04495
if (Peb->NumberOfHeaps == Peb->MaximumNumberOfHeaps) {
04496
04497
04498
04499
04500
04501 Peb->MaximumNumberOfHeaps *= 2;
04502
04503
04504
04505
04506
04507 NewList =
RtlAllocateHeap( RtlProcessHeap(),
04508 0,
04509 Peb->MaximumNumberOfHeaps *
sizeof( *NewList ));
04510
04511
if (NewList ==
NULL) {
04512
04513 leave;
04514 }
04515
04516
04517
04518
04519
04520 RtlMoveMemory( NewList,
04521 Peb->ProcessHeaps,
04522 Peb->NumberOfHeaps *
sizeof( *NewList ));
04523
04524
04525
04526
04527
04528
if (Peb->ProcessHeaps !=
RtlpProcessHeapsListBuffer) {
04529
04530
RtlFreeHeap( RtlProcessHeap(), 0, Peb->ProcessHeaps );
04531 }
04532
04533
04534
04535
04536
04537 Peb->ProcessHeaps = NewList;
04538 }
04539
04540
04541
04542
04543
04544
04545
04546 Peb->ProcessHeaps[ Peb->NumberOfHeaps++ ] = Heap;
04547 Heap->ProcessHeapsListIndex = (
USHORT)Peb->NumberOfHeaps;
04548
04549 } finally {
04550
04551
04552
04553
04554
04555
RtlReleaseLockRoutine( &
RtlpProcessHeapsListLock.
Lock );
04556 }
04557
04558
04559
04560
04561
04562
return;
04563 }
04564
04565
04566
04567
04568
04569
04570
VOID
04571 RtlpRemoveHeapFromProcessList (
04572 IN
PHEAP Heap
04573 )
04574
04575
04576
04577
04578
04579
04580
04581
04582
04583
04584
04585
04586
04587
04588
04589
04590
04591
04592 {
04593 PPEB Peb = NtCurrentPeb();
04594
PHEAP *p, *p1;
04595 ULONG
n;
04596
04597
04598
04599
04600
04601
RtlAcquireLockRoutine( &
RtlpProcessHeapsListLock.
Lock );
04602
04603
try {
04604
04605
04606
04607
04608
04609
04610
04611
if ((Peb->NumberOfHeaps != 0) &&
04612 (Heap->ProcessHeapsListIndex != 0) &&
04613 (Heap->ProcessHeapsListIndex <= Peb->NumberOfHeaps)) {
04614
04615
04616
04617
04618
04619
04620 p = (
PHEAP *)&Peb->ProcessHeaps[ Heap->ProcessHeapsListIndex - 1 ];
04621
04622 p1 = p + 1;
04623
04624
04625
04626
04627
04628
04629
n = Peb->NumberOfHeaps - (Heap->ProcessHeapsListIndex - 1);
04630
04631
04632
04633
04634
04635
04636
while (--
n) {
04637
04638
04639
04640
04641
04642
04643 *p = *p1++;
04644
04645
04646
04647
04648
04649
RtlpUpdateHeapListIndex( (*p)->ProcessHeapsListIndex,
04650 (
USHORT)((*p)->ProcessHeapsListIndex - 1));
04651
04652
04653
04654
04655
04656 (*p)->ProcessHeapsListIndex -= 1;
04657
04658
04659
04660
04661
04662 p += 1;
04663 }
04664
04665
04666
04667
04668
04669
04670
04671 Peb->ProcessHeaps[ --Peb->NumberOfHeaps ] =
NULL;
04672 Heap->ProcessHeapsListIndex = 0;
04673 }
04674
04675 } finally {
04676
04677
04678
04679
04680
04681
RtlReleaseLockRoutine( &
RtlpProcessHeapsListLock.
Lock );
04682 }
04683
04684
return;
04685 }
04686
04687
04688
04689
04690
04691
04692 BOOLEAN
04693 RtlpGrowBlockInPlace (
04694 IN
PHEAP Heap,
04695 IN ULONG Flags,
04696 IN
PHEAP_ENTRY BusyBlock,
04697 IN SIZE_T Size,
04698 IN SIZE_T AllocationIndex
04699 )
04700
04701
04702
04703
04704
04705
04706
04707
04708
04709
04710
04711
04712
04713
04714
04715
04716
04717
04718
04719
04720
04721
04722
04723
04724
04725
04726
04727
04728
04729 {
04730 SIZE_T FreeSize;
04731 SIZE_T OldSize;
04732 UCHAR EntryFlags, FreeFlags;
04733
PHEAP_FREE_ENTRY FreeBlock, SplitBlock, SplitBlock2;
04734
PHEAP_ENTRY_EXTRA OldExtraStuff, NewExtraStuff;
04735
04736
04737
04738
04739
04740
04741
if (AllocationIndex > Heap->VirtualMemoryThreshold) {
04742
04743
return FALSE;
04744 }
04745
04746
04747
04748
04749
04750
04751 EntryFlags = BusyBlock->Flags;
04752
04753 FreeBlock = (
PHEAP_FREE_ENTRY)(BusyBlock + BusyBlock->Size);
04754
04755
04756
04757
04758
04759
04760
if (EntryFlags &
HEAP_ENTRY_LAST_ENTRY) {
04761
04762
04763
04764
04765
04766
04767 FreeSize = (AllocationIndex - BusyBlock->Size) <<
HEAP_GRANULARITY_SHIFT;
04768 FreeSize =
ROUND_UP_TO_POWER2( FreeSize,
PAGE_SIZE );
04769
04770
04771
04772
04773
04774 FreeBlock =
RtlpFindAndCommitPages( Heap,
04775 Heap->Segments[ BusyBlock->SegmentIndex ],
04776 &FreeSize,
04777 (
PHEAP_ENTRY)FreeBlock );
04778
04779
04780
04781
04782
04783
if (FreeBlock ==
NULL) {
04784
04785
return FALSE;
04786 }
04787
04788
04789
04790
04791
04792
04793 FreeSize = FreeSize >>
HEAP_GRANULARITY_SHIFT;
04794
04795 FreeBlock =
RtlpCoalesceFreeBlocks( Heap, FreeBlock, &FreeSize,
FALSE );
04796
04797 FreeFlags = FreeBlock->
Flags;
04798
04799
04800
04801
04802
04803
04804
04805
04806
if ((FreeSize + BusyBlock->Size) < AllocationIndex) {
04807
04808
RtlpInsertFreeBlock( Heap, FreeBlock, FreeSize );
04809
04810 Heap->TotalFreeSize += FreeSize;
04811
04812
if (
DEBUG_HEAP(Flags)) {
04813
04814
RtlpValidateHeapHeaders( Heap,
TRUE );
04815 }
04816
04817
return FALSE;
04818 }
04819
04820
04821
04822
04823
04824
04825
04826 FreeSize += BusyBlock->Size;
04827
04828 }
else {
04829
04830
04831
04832
04833
04834
04835
04836 FreeFlags = FreeBlock->
Flags;
04837
04838
if (FreeFlags &
HEAP_ENTRY_BUSY) {
04839
04840
return FALSE;
04841 }
04842
04843
04844
04845
04846
04847
04848 FreeSize = BusyBlock->Size + FreeBlock->
Size;
04849
04850
if (FreeSize < AllocationIndex) {
04851
04852
return FALSE;
04853 }
04854
04855
04856
04857
04858
04859
04860
RtlpRemoveFreeBlock( Heap, FreeBlock );
04861
04862 Heap->TotalFreeSize -= FreeBlock->
Size;
04863 }
04864
04865
04866
04867
04868
04869
04870
04871
04872
04873
04874 OldSize = (BusyBlock->Size <<
HEAP_GRANULARITY_SHIFT) - BusyBlock->UnusedBytes;
04875
04876
04877
04878
04879
04880
04881 FreeSize -= AllocationIndex;
04882
04883
04884
04885
04886
04887
04888
if (FreeSize <= 2) {
04889
04890 AllocationIndex += FreeSize;
04891
04892 FreeSize = 0;
04893 }
04894
04895
04896
04897
04898
04899
04900
if (EntryFlags &
HEAP_ENTRY_EXTRA_PRESENT) {
04901
04902 OldExtraStuff = (
PHEAP_ENTRY_EXTRA)(BusyBlock + BusyBlock->Size - 1);
04903 NewExtraStuff = (
PHEAP_ENTRY_EXTRA)(BusyBlock + AllocationIndex - 1);
04904
04905 *NewExtraStuff = *OldExtraStuff;
04906
04907
04908
04909
04910
04911
04912
if (
IS_HEAP_TAGGING_ENABLED()) {
04913
04914 NewExtraStuff->
TagIndex =
04915
RtlpUpdateTagEntry( Heap,
04916 NewExtraStuff->
TagIndex,
04917 BusyBlock->Size,
04918 AllocationIndex,
04919
ReAllocationAction );
04920 }
04921
04922
04923
04924
04925
04926
04927 }
else if (
IS_HEAP_TAGGING_ENABLED()) {
04928
04929 BusyBlock->SmallTagIndex = (UCHAR)
04930
RtlpUpdateTagEntry( Heap,
04931 BusyBlock->SmallTagIndex,
04932 BusyBlock->Size,
04933 AllocationIndex,
04934
ReAllocationAction );
04935 }
04936
04937
04938
04939
04940
04941
if (FreeSize == 0) {
04942
04943
04944
04945
04946
04947
04948
04949 BusyBlock->Flags |= FreeFlags &
HEAP_ENTRY_LAST_ENTRY;
04950
04951 BusyBlock->Size = (
USHORT)AllocationIndex;
04952
04953 BusyBlock->UnusedBytes = (UCHAR)
04954 ((AllocationIndex <<
HEAP_GRANULARITY_SHIFT) -
Size);
04955
04956
04957
04958
04959
04960
if (!(FreeFlags &
HEAP_ENTRY_LAST_ENTRY)) {
04961
04962 (BusyBlock + BusyBlock->Size)->PreviousSize = BusyBlock->Size;
04963
04964 }
else {
04965
04966
PHEAP_SEGMENT Segment;
04967
04968 Segment = Heap->Segments[BusyBlock->SegmentIndex];
04969 Segment->
LastEntryInSegment = BusyBlock;
04970 }
04971
04972
04973
04974
04975
04976 }
else {
04977
04978
04979
04980
04981
04982 BusyBlock->
Size = (
USHORT)AllocationIndex;
04983
04984 BusyBlock->UnusedBytes = (UCHAR)
04985 ((AllocationIndex <<
HEAP_GRANULARITY_SHIFT) -
Size);
04986
04987
04988
04989
04990
04991 SplitBlock = (
PHEAP_FREE_ENTRY)((
PHEAP_ENTRY)BusyBlock + AllocationIndex);
04992
04993 SplitBlock->
PreviousSize = (
USHORT)AllocationIndex;
04994
04995 SplitBlock->
SegmentIndex = BusyBlock->SegmentIndex;
04996
04997
04998
04999
05000
05001
05002
if (FreeFlags &
HEAP_ENTRY_LAST_ENTRY) {
05003
05004
PHEAP_SEGMENT Segment;
05005
05006 Segment = Heap->Segments[SplitBlock->
SegmentIndex];
05007 Segment->
LastEntryInSegment = (
PHEAP_ENTRY)SplitBlock;
05008
05009 SplitBlock->
Flags = FreeFlags;
05010 SplitBlock->
Size = (
USHORT)FreeSize;
05011
05012
RtlpInsertFreeBlockDirect( Heap, SplitBlock, (
USHORT)FreeSize );
05013
05014 Heap->TotalFreeSize += FreeSize;
05015
05016
05017
05018
05019
05020 }
else {
05021
05022
05023
05024
05025
05026 SplitBlock2 = (
PHEAP_FREE_ENTRY)((
PHEAP_ENTRY)SplitBlock + FreeSize);
05027
05028
05029
05030
05031
05032
05033
05034
05035
if (SplitBlock2->
Flags &
HEAP_ENTRY_BUSY) {
05036
05037 SplitBlock->
Flags = FreeFlags & (~
HEAP_ENTRY_LAST_ENTRY);
05038 SplitBlock->
Size = (
USHORT)FreeSize;
05039
05040
05041
05042
05043
05044
05045
05046
if (!(FreeFlags &
HEAP_ENTRY_LAST_ENTRY)) {
05047
05048 ((
PHEAP_ENTRY)SplitBlock + FreeSize)->PreviousSize = (
USHORT)FreeSize;
05049
05050 }
else {
05051
05052
PHEAP_SEGMENT Segment;
05053
05054 Segment = Heap->Segments[SplitBlock->
SegmentIndex];
05055 Segment->
LastEntryInSegment = (
PHEAP_ENTRY)SplitBlock;
05056 }
05057
05058
RtlpInsertFreeBlockDirect( Heap, SplitBlock, (
USHORT)FreeSize );
05059
05060 Heap->TotalFreeSize += FreeSize;
05061
05062
05063
05064
05065
05066
05067 }
else {
05068
05069
05070
05071
05072
05073 FreeFlags = SplitBlock2->
Flags;
05074
05075
05076
05077
05078
05079
RtlpRemoveFreeBlock( Heap, SplitBlock2 );
05080
05081 Heap->TotalFreeSize -= SplitBlock2->
Size;
05082
05083
05084
05085
05086
05087 FreeSize += SplitBlock2->
Size;
05088
05089
05090
05091
05092
05093 SplitBlock->
Flags = FreeFlags;
05094
05095
05096
05097
05098
05099
05100
if (FreeSize <=
HEAP_MAXIMUM_BLOCK_SIZE) {
05101
05102 SplitBlock->
Size = (
USHORT)FreeSize;
05103
05104
05105
05106
05107
05108
if (!(FreeFlags &
HEAP_ENTRY_LAST_ENTRY)) {
05109
05110 ((
PHEAP_ENTRY)SplitBlock + FreeSize)->PreviousSize = (
USHORT)FreeSize;
05111
05112 }
else {
05113
05114
PHEAP_SEGMENT Segment;
05115
05116 Segment = Heap->Segments[SplitBlock->
SegmentIndex];
05117 Segment->
LastEntryInSegment = (
PHEAP_ENTRY)SplitBlock;
05118 }
05119
05120
05121
05122
05123
05124
RtlpInsertFreeBlockDirect( Heap, SplitBlock, (
USHORT)FreeSize );
05125
05126 Heap->TotalFreeSize += FreeSize;
05127
05128 }
else {
05129
05130
05131
05132
05133
05134
05135
05136
RtlpInsertFreeBlock( Heap, SplitBlock, FreeSize );
05137 }
05138 }
05139 }
05140 }
05141
05142
05143
05144
05145
05146
05147
05148
05149
if (Flags & HEAP_ZERO_MEMORY) {
05150
05151
05152
05153
05154
05155
05156
if (
Size > OldSize) {
05157
05158 RtlZeroMemory( (PCHAR)(BusyBlock + 1) + OldSize,
05159
Size - OldSize );
05160 }
05161
05162
05163
05164
05165
05166
05167
05168 }
else if (Heap->Flags & HEAP_FREE_CHECKING_ENABLED) {
05169
05170 SIZE_T PartialBytes, ExtraSize;
05171
05172 PartialBytes = OldSize & (
sizeof( ULONG ) - 1);
05173
05174
if (PartialBytes) {
05175
05176 PartialBytes = 4 - PartialBytes;
05177 }
05178
05179
if (
Size > (OldSize + PartialBytes)) {
05180
05181 ExtraSize = (
Size - (OldSize + PartialBytes)) & ~(
sizeof( ULONG ) - 1);
05182
05183
if (ExtraSize != 0) {
05184
05185 RtlFillMemoryUlong( (PCHAR)(BusyBlock + 1) + OldSize + PartialBytes,
05186 ExtraSize,
05187
ALLOC_HEAP_FILL );
05188 }
05189 }
05190 }
05191
05192
05193
05194
05195
05196
05197
if (Heap->Flags & HEAP_TAIL_CHECKING_ENABLED) {
05198
05199 RtlFillMemory( (PCHAR)(BusyBlock + 1) +
Size,
05200
CHECK_HEAP_TAIL_SIZE,
05201
CHECK_HEAP_TAIL_FILL );
05202 }
05203
05204
05205
05206
05207
05208
05209 BusyBlock->Flags &= ~
HEAP_ENTRY_SETTABLE_FLAGS;
05210 BusyBlock->Flags |= ((Flags & HEAP_SETTABLE_USER_FLAGS) >> 4);
05211
05212
05213
05214
05215
05216
return TRUE;
05217 }
05218
05219
05220
05221
05222
05223
05224
PHEAP_TAG_ENTRY
05225 RtlpAllocateTags (
05226
PHEAP Heap,
05227 ULONG NumberOfTags
05228 )
05229
05230
05231
05232
05233
05234
05235
05236
05237
05238
05239
05240
05241
05242
05243
05244
05245
05246
05247
05248
05249
05250
05251
05252 {
05253
NTSTATUS Status;
05254 ULONG TagIndex;
05255 SIZE_T ReserveSize;
05256 SIZE_T CommitSize;
05257
PHEAP_TAG_ENTRY TagEntry;
05258
USHORT CreatorBackTraceIndex;
05259
USHORT MaximumTagIndex;
05260
USHORT TagIndexFlag;
05261
05262
05263
05264
05265
05266
05267
if (
RtlpGlobalTagHeap ==
NULL) {
05268
05269
return NULL;
05270 }
05271
05272
05273
05274
05275
05276
05277
if (Heap ==
NULL) {
05278
05279
RtlpGlobalTagHeap->
Signature =
HEAP_SIGNATURE;
05280
05281
RtlpGlobalTagHeap->
Flags = HEAP_NO_SERIALIZE;
05282
05283 TagIndexFlag = HEAP_GLOBAL_TAG;
05284
05285 Heap =
RtlpGlobalTagHeap;
05286
05287 }
else {
05288
05289 TagIndexFlag = 0;
05290 }
05291
05292
05293
05294
05295
05296 CreatorBackTraceIndex = 0;
05297
05298
#if i386
05299
05300
if (Heap->
Flags &
HEAP_CAPTURE_STACK_BACKTRACES) {
05301
05302 CreatorBackTraceIndex = (
USHORT)RtlLogStackBackTrace();
05303 }
05304
05305
#endif // i386
05306
05307
05308
05309
05310
05311
05312
if (Heap->
TagEntries ==
NULL) {
05313
05314 MaximumTagIndex = HEAP_MAXIMUM_TAG & ~HEAP_GLOBAL_TAG;
05315
05316 ReserveSize = MaximumTagIndex *
sizeof(
HEAP_TAG_ENTRY );
05317
05318
Status =
NtAllocateVirtualMemory( NtCurrentProcess(),
05319 &Heap->
TagEntries,
05320 0,
05321 &ReserveSize,
05322 MEM_RESERVE,
05323 PAGE_READWRITE );
05324
05325
if (!
NT_SUCCESS(
Status )) {
05326
05327
return NULL;
05328 }
05329
05330 Heap->
MaximumTagIndex = MaximumTagIndex;
05331
05332 Heap->
NextAvailableTagIndex = 0;
05333
05334
05335
05336
05337
05338 NumberOfTags += 1;
05339 }
05340
05341
05342
05343
05344
05345
05346
05347
if (NumberOfTags > (ULONG)(Heap->
MaximumTagIndex - Heap->
NextAvailableTagIndex)) {
05348
05349
return NULL;
05350 }
05351
05352
05353
05354
05355
05356
05357
05358
05359
05360 TagEntry = Heap->
TagEntries + Heap->
NextAvailableTagIndex;
05361
05362
for (TagIndex = Heap->
NextAvailableTagIndex;
05363 TagIndex < Heap->
NextAvailableTagIndex + NumberOfTags;
05364 TagIndex++ ) {
05365
05366
if (((((ULONG_PTR)TagEntry +
sizeof(*TagEntry)) & (
PAGE_SIZE-1)) <=
05367
sizeof(*TagEntry))) {
05368
05369 CommitSize =
PAGE_SIZE;
05370
05371
Status =
NtAllocateVirtualMemory( NtCurrentProcess(),
05372 &TagEntry,
05373 0,
05374 &CommitSize,
05375 MEM_COMMIT,
05376 PAGE_READWRITE );
05377
05378
if (!
NT_SUCCESS(
Status )) {
05379
05380
return NULL;
05381 }
05382 }
05383
05384
05385
05386
05387
05388 TagEntry->
TagIndex = (
USHORT)TagIndex | TagIndexFlag;
05389
05390
05391
05392
05393
05394 TagEntry->
CreatorBackTraceIndex = CreatorBackTraceIndex;
05395
05396
05397
05398
05399
05400 TagEntry += 1;
05401 }
05402
05403
05404
05405
05406
05407
05408 TagEntry = Heap->
TagEntries + Heap->
NextAvailableTagIndex;
05409
05410 Heap->
NextAvailableTagIndex += (
USHORT)NumberOfTags;
05411
05412
05413
05414
05415
05416
return TagEntry;
05417 }
05418
05419
05420
05421
05422
05423
05424 PWSTR
05425 RtlpGetTagName (
05426
PHEAP Heap,
05427 USHORT TagIndex
05428 )
05429
05430
05431
05432
05433
05434
05435
05436
05437
05438
05439
05440
05441
05442
05443
05444
05445
05446
05447
05448
05449
05450
05451
05452 {
05453
05454
05455
05456
05457
05458
if (
RtlpGlobalTagHeap ==
NULL) {
05459
05460
return NULL;
05461 }
05462
05463
05464
05465
05466
05467
if (TagIndex != 0) {
05468
05469
05470
05471
05472
05473
05474
if (TagIndex & HEAP_PSEUDO_TAG_FLAG) {
05475
05476 TagIndex &= ~HEAP_PSEUDO_TAG_FLAG;
05477
05478
05479
05480
05481
05482
05483
if ((TagIndex <
HEAP_NUMBER_OF_PSEUDO_TAG) &&
05484 (Heap->
PseudoTagEntries !=
NULL)) {
05485
05486
05487
05488
05489
05490
if (TagIndex == 0) {
05491
05492 swprintf(
RtlpPseudoTagNameBuffer,
L"Objects>%4u",
05493
HEAP_MAXIMUM_FREELISTS <<
HEAP_GRANULARITY_SHIFT );
05494
05495
05496
05497
05498
05499
05500 }
else if (TagIndex <
HEAP_MAXIMUM_FREELISTS) {
05501
05502 swprintf(
RtlpPseudoTagNameBuffer,
L"Objects=%4u", TagIndex <<
HEAP_GRANULARITY_SHIFT );
05503
05504
05505
05506
05507
05508 }
else {
05509
05510 swprintf(
RtlpPseudoTagNameBuffer,
L"VirtualAlloc" );
05511 }
05512
05513
return RtlpPseudoTagNameBuffer;
05514 }
05515
05516
05517
05518
05519
05520
05521
05522 }
else if (TagIndex & HEAP_GLOBAL_TAG) {
05523
05524 TagIndex &= ~HEAP_GLOBAL_TAG;
05525
05526
if ((TagIndex <
RtlpGlobalTagHeap->
NextAvailableTagIndex) &&
05527 (
RtlpGlobalTagHeap->
TagEntries !=
NULL)) {
05528
05529
return RtlpGlobalTagHeap->
TagEntries[ TagIndex ].
TagName;
05530 }
05531
05532
05533
05534
05535
05536
05537
05538 }
else if ((TagIndex < Heap->
NextAvailableTagIndex) &&
05539 (Heap->
TagEntries !=
NULL)) {
05540
05541
return Heap->
TagEntries[ TagIndex ].
TagName;
05542 }
05543 }
05544
05545
return NULL;
05546 }
05547
05548
05549
05550
05551
05552
05553
USHORT
05554 RtlpUpdateTagEntry (
05555
PHEAP Heap,
05556 USHORT TagIndex,
05557 SIZE_T OldSize,
05558 SIZE_T NewSize,
05559
HEAP_TAG_ACTION Action
05560 )
05561
05562
05563
05564
05565
05566
05567
05568
05569
05570
05571
05572
05573
05574
05575
05576
05577
05578
05579
05580
05581
05582
05583
05584
05585
05586 {
05587
PHEAP_TAG_ENTRY TagEntry;
05588
05589
05590
05591
05592
05593
05594
if (
RtlpGlobalTagHeap ==
NULL) {
05595
05596
return 0;
05597 }
05598
05599
05600
05601
05602
05603
05604
05605
05606
if (
Action >=
FreeAction) {
05607
05608
05609
05610
05611
05612
if (TagIndex == 0) {
05613
05614
return 0;
05615 }
05616
05617
05618
05619
05620
05621
05622
05623
if (TagIndex & HEAP_PSEUDO_TAG_FLAG) {
05624
05625 TagIndex &= ~HEAP_PSEUDO_TAG_FLAG;
05626
05627
if ((TagIndex <
HEAP_NUMBER_OF_PSEUDO_TAG) &&
05628 (Heap->
PseudoTagEntries !=
NULL)) {
05629
05630 TagEntry = (
PHEAP_TAG_ENTRY)(Heap->
PseudoTagEntries + TagIndex);
05631
05632 TagIndex |= HEAP_PSEUDO_TAG_FLAG;
05633
05634 }
else {
05635
05636
return 0;
05637 }
05638
05639
05640
05641
05642
05643
05644
05645 }
else if (TagIndex & HEAP_GLOBAL_TAG) {
05646
05647 TagIndex &= ~HEAP_GLOBAL_TAG;
05648
05649
if ((TagIndex <
RtlpGlobalTagHeap->
NextAvailableTagIndex) &&
05650 (
RtlpGlobalTagHeap->
TagEntries !=
NULL)) {
05651
05652 TagEntry = &
RtlpGlobalTagHeap->
TagEntries[ TagIndex ];
05653
05654 TagIndex |= HEAP_GLOBAL_TAG;
05655
05656 }
else {
05657
05658
return 0;
05659 }
05660
05661
05662
05663
05664
05665
05666 }
else if ((TagIndex < Heap->
NextAvailableTagIndex) &&
05667 (Heap->
TagEntries !=
NULL)) {
05668
05669 TagEntry = &Heap->
TagEntries[ TagIndex ];
05670
05671 }
else {
05672
05673
return 0;
05674 }
05675
05676
05677
05678
05679
05680
05681
05682 TagEntry->
Frees += 1;
05683
05684 TagEntry->
Size -= OldSize;
05685
05686
05687
05688
05689
05690
05691
05692
if (
Action >=
ReAllocationAction) {
05693
05694
05695
05696
05697
05698
05699
if (TagIndex & HEAP_PSEUDO_TAG_FLAG) {
05700
05701 TagIndex = (
USHORT)(NewSize <
HEAP_MAXIMUM_FREELISTS ?
05702 NewSize :
05703 (
Action ==
VirtualReAllocationAction ?
HEAP_MAXIMUM_FREELISTS : 0));
05704
05705 TagEntry = (
PHEAP_TAG_ENTRY)(Heap->
PseudoTagEntries + TagIndex);
05706
05707 TagIndex |= HEAP_PSEUDO_TAG_FLAG;
05708 }
05709
05710 TagEntry->
Allocs += 1;
05711
05712 TagEntry->
Size += NewSize;
05713 }
05714
05715
05716
05717
05718
05719 }
else {
05720
05721
05722
05723
05724
05725
05726
if ((TagIndex != 0) &&
05727 (TagIndex < Heap->
NextAvailableTagIndex) &&
05728 (Heap->
TagEntries !=
NULL)) {
05729
05730 TagEntry = &Heap->
TagEntries[ TagIndex ];
05731
05732
05733
05734
05735
05736
05737 }
else if (TagIndex & HEAP_GLOBAL_TAG) {
05738
05739 TagIndex &= ~HEAP_GLOBAL_TAG;
05740
05741 Heap =
RtlpGlobalTagHeap;
05742
05743
if ((TagIndex < Heap->
NextAvailableTagIndex) &&
05744 (Heap->
TagEntries !=
NULL)) {
05745
05746 TagEntry = &Heap->
TagEntries[ TagIndex ];
05747
05748 TagIndex |= HEAP_GLOBAL_TAG;
05749
05750 }
else {
05751
05752
return 0;
05753 }
05754
05755
05756
05757
05758
05759
05760 }
else if (Heap->
PseudoTagEntries !=
NULL) {
05761
05762 TagIndex = (
USHORT)(NewSize <
HEAP_MAXIMUM_FREELISTS ?
05763 NewSize :
05764 (
Action ==
VirtualAllocationAction ?
HEAP_MAXIMUM_FREELISTS : 0));
05765
05766 TagEntry = (
PHEAP_TAG_ENTRY)(Heap->
PseudoTagEntries + TagIndex);
05767
05768 TagIndex |= HEAP_PSEUDO_TAG_FLAG;
05769
05770
05771
05772
05773
05774 }
else {
05775
05776
return 0;
05777 }
05778
05779
05780
05781
05782
05783
05784 TagEntry->
Allocs += 1;
05785
05786 TagEntry->
Size += NewSize;
05787 }
05788
05789
05790
05791
05792
05793
return TagIndex;
05794 }
05795
05796
05797
05798
05799
05800
05801
VOID
05802 RtlpResetTags (
05803
PHEAP Heap
05804 )
05805
05806
05807
05808
05809
05810
05811
05812
05813
05814
05815
05816
05817
05818
05819
05820
05821
05822 {
05823
PHEAP_TAG_ENTRY TagEntry;
05824
PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntry;
05825 ULONG i;
05826
05827
05828
05829
05830
05831 TagEntry = Heap->
TagEntries;
05832
05833
if (TagEntry !=
NULL) {
05834
05835
05836
05837
05838
05839
for (i=0; i<Heap->
NextAvailableTagIndex; i++) {
05840
05841 TagEntry->
Allocs = 0;
05842 TagEntry->
Frees = 0;
05843 TagEntry->
Size = 0;
05844
05845
05846
05847
05848
05849 TagEntry += 1;
05850 }
05851 }
05852
05853
05854
05855
05856
05857 PseudoTagEntry = Heap->
PseudoTagEntries;
05858
05859
if (PseudoTagEntry !=
NULL) {
05860
05861
05862
05863
05864
05865
05866
for (i=0; i<
HEAP_NUMBER_OF_PSEUDO_TAG; i++) {
05867
05868 PseudoTagEntry->
Allocs = 0;
05869 PseudoTagEntry->
Frees = 0;
05870 PseudoTagEntry->
Size = 0;
05871
05872
05873
05874
05875
05876 PseudoTagEntry += 1;
05877 }
05878 }
05879
05880
05881
05882
05883
05884
return;
05885 }
05886
05887
05888
05889
05890
05891
05892
VOID
05893 RtlpDestroyTags (
05894
PHEAP Heap
05895 )
05896
05897
05898
05899
05900
05901
05902
05903
05904
05905
05906
05907
05908
05909
05910
05911
05912
05913
05914 {
05915
NTSTATUS Status;
05916 SIZE_T RegionSize;
05917
05918
05919
05920
05921
05922
if (Heap->
TagEntries !=
NULL) {
05923
05924
05925
05926
05927
05928 RegionSize = 0;
05929
05930
Status =
NtFreeVirtualMemory( NtCurrentProcess(),
05931 &Heap->
TagEntries,
05932 &RegionSize,
05933 MEM_RELEASE );
05934
05935
if (
NT_SUCCESS(
Status )) {
05936
05937 Heap->
TagEntries =
NULL;
05938 }
05939 }
05940
05941
05942
05943
05944
05945
return;
05946 }
05947
05948
05949
05950
05951
05952
05953
NTSTATUS
05954 RtlpAllocateHeapUsageEntry (
05955 PRTL_HEAP_USAGE_INTERNAL Buffer,
05956 PRTL_HEAP_USAGE_ENTRY *pp
05957 )
05958
05959
05960
05961
05962
05963
05964
05965
05966
05967
05968
05969
05970
05971
05972
05973
05974
05975
05976
05977
05978
05979
05980
05981
05982
05983 {
05984
NTSTATUS Status;
05985 PRTL_HEAP_USAGE_ENTRY p;
05986 PVOID CommitAddress;
05987 SIZE_T PageSize;
05988
05989
05990
05991
05992
05993
05994
if (
Buffer->FreeList ==
NULL) {
05995
05996
05997
05998
05999
06000
if (
Buffer->CommittedSize >=
Buffer->ReservedSize) {
06001
06002
return STATUS_NO_MEMORY;
06003 }
06004
06005
06006
06007
06008
06009
06010 PageSize =
PAGE_SIZE;
06011
06012 CommitAddress = (PCHAR)
Buffer->Base +
Buffer->CommittedSize;
06013
06014
Status =
NtAllocateVirtualMemory( NtCurrentProcess(),
06015 &CommitAddress,
06016 0,
06017 &PageSize,
06018 MEM_COMMIT,
06019 PAGE_READWRITE );
06020
06021
if (!
NT_SUCCESS(
Status )) {
06022
06023
return Status;
06024 }
06025
06026
06027
06028
06029
06030
Buffer->CommittedSize += PageSize;
06031
06032
06033
06034
06035
06036
06037
Buffer->FreeList = CommitAddress;
06038
06039 p =
Buffer->FreeList;
06040
06041
while (PageSize != 0) {
06042
06043 p->Next = (p+1);
06044 p += 1;
06045 PageSize -=
sizeof( *p );
06046 }
06047
06048
06049
06050
06051
06052 p -= 1;
06053 p->Next =
NULL;
06054 }
06055
06056
06057
06058
06059
06060
06061 p =
Buffer->FreeList;
06062
06063
Buffer->FreeList = p->Next;
06064
06065 p->Next =
NULL;
06066
06067
06068
06069
06070
06071
06072
if (*pp) {
06073
06074 (*pp)->Next = p;
06075 }
06076
06077
06078
06079
06080
06081 *pp = p;
06082
06083
return STATUS_SUCCESS;
06084 }
06085
06086
06087
06088
06089
06090
06091 PRTL_HEAP_USAGE_ENTRY
06092 RtlpFreeHeapUsageEntry (
06093 PRTL_HEAP_USAGE_INTERNAL Buffer,
06094 PRTL_HEAP_USAGE_ENTRY p
06095 )
06096
06097
06098
06099
06100
06101
06102
06103
06104
06105
06106
06107
06108
06109
06110
06111
06112
06113
06114
06115
06116
06117
06118
06119
06120
06121 {
06122 PRTL_HEAP_USAGE_ENTRY pTmp;
06123
06124
06125
06126
06127
06128
06129
06130
if (p !=
NULL) {
06131
06132 pTmp = p->Next;
06133
06134 p->Next =
Buffer->FreeList;
06135
06136
Buffer->FreeList = p;
06137
06138 }
else {
06139
06140 pTmp =
NULL;
06141 }
06142
06143
return pTmp;
06144 }
06145
06146
06147
06148
06149
06150
06151 BOOLEAN
06152 RtlpHeapIsLocked (
06153 IN PVOID HeapHandle
06154 )
06155
06156
06157
06158
06159
06160
06161
06162
06163
06164
06165
06166
06167
06168
06169
06170
06171
06172 {
06173
PHEAP Heap;
06174
06175
06176
06177
06178
06179
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
06180
RtlpDebugPageHeapIsLocked(
HeapHandle ));
06181
06182 Heap = (
PHEAP)
HeapHandle;
06183
06184
06185
06186
06187
06188
06189
return (( Heap->
LockVariable !=
NULL ) &&
06190 ( Heap->
LockVariable->
Lock.CriticalSection.OwningThread ||
06191 Heap->
LockVariable->
Lock.CriticalSection.LockCount != -1 ));
06192 }
06193