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 BOOLEAN
RtlpValidateHeapHdrsEnable =
FALSE;
00026 BOOLEAN
RtlpValidateHeapTagsEnable;
00027
00028 HEAP_STOP_ON_VALUES RtlpHeapStopOn;
00029
00030
00031
const struct {
00032
00033 ULONG
Offset;
00034 LPSTR
Description;
00035
00036 }
RtlpHeapHeaderFieldOffsets[] = {
00037
00038 FIELD_OFFSET(
HEAP, Entry ),
"Entry",
00039 FIELD_OFFSET(
HEAP, Signature ),
"Signature",
00040 FIELD_OFFSET(
HEAP, Flags ),
"Flags",
00041 FIELD_OFFSET(
HEAP, ForceFlags ),
"ForceFlags",
00042 FIELD_OFFSET(
HEAP, VirtualMemoryThreshold ),
"VirtualMemoryThreshold",
00043 FIELD_OFFSET(
HEAP, SegmentReserve ),
"SegmentReserve",
00044 FIELD_OFFSET(
HEAP, SegmentCommit ),
"SegmentCommit",
00045 FIELD_OFFSET(
HEAP, DeCommitFreeBlockThreshold ),
"DeCommitFreeBlockThreshold",
00046 FIELD_OFFSET(
HEAP, DeCommitTotalFreeThreshold ),
"DeCommitTotalFreeThreshold",
00047 FIELD_OFFSET(
HEAP, TotalFreeSize ),
"TotalFreeSize",
00048 FIELD_OFFSET(
HEAP, MaximumAllocationSize ),
"MaximumAllocationSize",
00049 FIELD_OFFSET(
HEAP, ProcessHeapsListIndex ),
"ProcessHeapsListIndex",
00050 FIELD_OFFSET(
HEAP, HeaderValidateLength ),
"HeaderValidateLength",
00051 FIELD_OFFSET(
HEAP, HeaderValidateCopy ),
"HeaderValidateCopy",
00052 FIELD_OFFSET(
HEAP, NextAvailableTagIndex ),
"NextAvailableTagIndex",
00053 FIELD_OFFSET(
HEAP, MaximumTagIndex ),
"MaximumTagIndex",
00054 FIELD_OFFSET(
HEAP, TagEntries ),
"TagEntries",
00055 FIELD_OFFSET(
HEAP, UCRSegments ),
"UCRSegments",
00056 FIELD_OFFSET(
HEAP, UnusedUnCommittedRanges ),
"UnusedUnCommittedRanges",
00057 FIELD_OFFSET(
HEAP, AlignRound ),
"AlignRound",
00058 FIELD_OFFSET(
HEAP, AlignMask ),
"AlignMask",
00059 FIELD_OFFSET(
HEAP, VirtualAllocdBlocks ),
"VirtualAllocdBlocks",
00060 FIELD_OFFSET(
HEAP, Segments ),
"Segments",
00061 FIELD_OFFSET(
HEAP, u ),
"FreeListsInUse",
00062 FIELD_OFFSET(
HEAP, FreeListsInUseTerminate ),
"FreeListsInUseTerminate",
00063 FIELD_OFFSET(
HEAP, AllocatorBackTraceIndex ),
"AllocatorBackTraceIndex",
00064 FIELD_OFFSET(
HEAP,
Reserved1 ),
"Reserved1",
00065 FIELD_OFFSET(
HEAP, PseudoTagEntries ),
"PseudoTagEntries",
00066 FIELD_OFFSET(
HEAP, FreeLists ),
"FreeLists",
00067 FIELD_OFFSET(
HEAP, LockVariable ),
"LockVariable",
00068 FIELD_OFFSET(
HEAP, Lookaside ),
"Lookaside",
00069 FIELD_OFFSET(
HEAP, LookasideLockCount ),
"LookasideLockCount",
00070
sizeof(
HEAP ),
"Uncommitted Ranges",
00071 0xFFFF,
NULL
00072 };
00073
00074
00075
VOID
00076 RtlpUpdateHeapListIndex (
00077 USHORT OldIndex,
00078 USHORT NewIndex
00079 )
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 {
00092
if (
RtlpHeapStopOn.
AllocTag.
HeapIndex == OldIndex) {
00093
00094
RtlpHeapStopOn.
AllocTag.
HeapIndex = NewIndex;
00095 }
00096
00097
if (
RtlpHeapStopOn.
ReAllocTag.
HeapIndex == OldIndex) {
00098
00099
RtlpHeapStopOn.
ReAllocTag.
HeapIndex = NewIndex;
00100 }
00101
00102
if (
RtlpHeapStopOn.
FreeTag.
HeapIndex == OldIndex) {
00103
00104
RtlpHeapStopOn.
FreeTag.
HeapIndex = NewIndex;
00105 }
00106
00107
return;
00108 }
00109
00110
00111 BOOLEAN
00112 RtlpValidateHeapHeaders (
00113 IN
PHEAP Heap,
00114 IN BOOLEAN Recompute
00115 )
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 {
00128 ULONG i;
00129 SIZE_T
n;
00130 SIZE_T nEqual;
00131
NTSTATUS Status;
00132
00133
if (!
RtlpValidateHeapHdrsEnable) {
00134
00135
return TRUE;
00136 }
00137
00138
if (Heap->HeaderValidateCopy ==
NULL) {
00139
00140
n = Heap->HeaderValidateLength;
00141
00142
Status =
NtAllocateVirtualMemory( NtCurrentProcess(),
00143 &Heap->HeaderValidateCopy,
00144 0,
00145 &
n,
00146 MEM_COMMIT,
00147 PAGE_READWRITE );
00148
00149
if (!
NT_SUCCESS(
Status )) {
00150
00151
return TRUE;
00152 }
00153
00154 Recompute =
TRUE;
00155 }
00156
00157
n = Heap->HeaderValidateLength;
00158
00159
if (!Recompute) {
00160
00161 nEqual = RtlCompareMemory( Heap,
00162 Heap->HeaderValidateCopy,
00163
n );
00164
00165 }
else {
00166
00167 RtlMoveMemory( Heap->HeaderValidateCopy,
00168 Heap,
00169
n );
00170
00171 nEqual =
n;
00172 }
00173
00174
if (
n != nEqual) {
00175
00176
HeapDebugPrint((
"Heap %x - headers modified (%x is %x instead of %x)\n",
00177 Heap,
00178 (PCHAR)Heap + nEqual,
00179 *(PULONG)((PCHAR)Heap + nEqual),
00180 *(PULONG)((PCHAR)Heap->HeaderValidateCopy + nEqual)));
00181
00182
for (i=0;
RtlpHeapHeaderFieldOffsets[ i ].Description !=
NULL; i++) {
00183
00184
if ((nEqual >=
RtlpHeapHeaderFieldOffsets[ i ].Offset) &&
00185 (nEqual <
RtlpHeapHeaderFieldOffsets[ i+1 ].Offset)) {
00186
00187
DbgPrint(
" This is located in the %s field of the heap header.\n",
00188
RtlpHeapHeaderFieldOffsets[ i ].
Description );
00189
00190
break;
00191 }
00192 }
00193
00194
return FALSE;
00195
00196 }
else {
00197
00198
return TRUE;
00199 }
00200 }
00201
00202
00203 PVOID
00204 RtlDebugCreateHeap (
00205 IN ULONG Flags,
00206 IN PVOID HeapBase OPTIONAL,
00207 IN SIZE_T ReserveSize OPTIONAL,
00208 IN SIZE_T CommitSize OPTIONAL,
00209 IN PVOID Lock OPTIONAL,
00210 IN PRTL_HEAP_PARAMETERS Parameters
00211 )
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 {
00224
PHEAP Heap;
00225
NTSTATUS Status;
00226 MEMORY_BASIC_INFORMATION MemoryInformation;
00227
00228
if (ReserveSize <=
sizeof(
HEAP_ENTRY )) {
00229
00230
HeapDebugPrint((
"Invalid ReserveSize parameter - %lx\n", ReserveSize ));
00231
HeapDebugBreak(
NULL );
00232
00233
return NULL;
00234 }
00235
00236
if (ReserveSize < CommitSize) {
00237
00238
HeapDebugPrint((
"Invalid CommitSize parameter - %lx\n", CommitSize ));
00239
HeapDebugBreak(
NULL );
00240
00241
return NULL;
00242 }
00243
00244
if ((Flags & HEAP_NO_SERIALIZE) && ARGUMENT_PRESENT(
Lock )) {
00245
00246
HeapDebugPrint((
"May not specify Lock parameter with HEAP_NO_SERIALIZE\n" ));
00247
HeapDebugBreak(
NULL );
00248
00249
return NULL;
00250 }
00251
00252
if (ARGUMENT_PRESENT( HeapBase )) {
00253
00254
Status =
NtQueryVirtualMemory( NtCurrentProcess(),
00255 HeapBase,
00256 MemoryBasicInformation,
00257 &MemoryInformation,
00258
sizeof( MemoryInformation ),
00259
NULL );
00260
00261
if (!
NT_SUCCESS(
Status )) {
00262
00263
HeapDebugPrint((
"Specified HeapBase (%lx) invalid, Status = %lx\n",
00264 HeapBase,
00265
Status ));
00266
00267
HeapDebugBreak(
NULL );
00268
00269
return NULL;
00270 }
00271
00272
if (MemoryInformation.BaseAddress != HeapBase) {
00273
00274
HeapDebugPrint((
"Specified HeapBase (%lx) != to BaseAddress (%lx)\n",
00275 HeapBase,
00276 MemoryInformation.BaseAddress ));
00277
00278
HeapDebugBreak(
NULL );
00279
00280
return NULL;
00281 }
00282
00283
if (MemoryInformation.State == MEM_FREE) {
00284
00285
HeapDebugPrint((
"Specified HeapBase (%lx) is free or not writable\n",
00286 MemoryInformation.BaseAddress ));
00287
00288
HeapDebugBreak(
NULL );
00289
00290
return NULL;
00291 }
00292 }
00293
00294 Heap =
RtlCreateHeap( Flags |
00295
HEAP_SKIP_VALIDATION_CHECKS |
00296 HEAP_TAIL_CHECKING_ENABLED |
00297 HEAP_FREE_CHECKING_ENABLED,
00298 HeapBase,
00299 ReserveSize,
00300 CommitSize,
00301
Lock,
00302 Parameters );
00303
00304
if (Heap !=
NULL) {
00305
00306
#if i386
00307
00308
if (Heap->
Flags &
HEAP_CAPTURE_STACK_BACKTRACES) {
00309
00310 Heap->
AllocatorBackTraceIndex = (
USHORT)RtlLogStackBackTrace();
00311 }
00312
00313
#endif // i386
00314
00315
RtlpValidateHeapHeaders( Heap,
TRUE );
00316 }
00317
00318
return Heap;
00319 }
00320
00321
00322 BOOLEAN
00323 RtlpSerializeHeap (
00324 IN PVOID HeapHandle
00325 )
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 {
00338
NTSTATUS Status;
00339
PHEAP Heap = (
PHEAP)
HeapHandle;
00340
PHEAP_LOCK Lock;
00341
00342
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
00343
RtlpDebugPageHeapSerialize(
HeapHandle ));
00344
00345
00346
00347
00348
00349
if (!
RtlpCheckHeapSignature( Heap,
"RtlpSerializeHeap" )) {
00350
00351
return FALSE;
00352 }
00353
00354
00355
00356
00357
00358
if (Heap->
Flags & HEAP_NO_SERIALIZE) {
00359
00360
Lock =
RtlAllocateHeap(
HeapHandle, HEAP_NO_SERIALIZE,
sizeof( *
Lock ) );
00361
00362
if (
Lock ==
NULL ) {
00363
00364
return FALSE;
00365 }
00366
00367
Status =
RtlInitializeLockRoutine(
Lock );
00368
00369
if (!
NT_SUCCESS(
Status )) {
00370
00371
RtlFreeHeap(
HeapHandle, HEAP_NO_SERIALIZE,
Lock );
00372
00373
return FALSE;
00374 }
00375
00376 Heap->
LockVariable =
Lock;
00377 Heap->
Flags &= ~HEAP_NO_SERIALIZE;
00378 Heap->
ForceFlags &= ~HEAP_NO_SERIALIZE;
00379
00380
RtlpValidateHeapHeaders( Heap,
TRUE );
00381 }
00382
00383
return TRUE;
00384 }
00385
00386
00387 BOOLEAN
00388 RtlDebugDestroyHeap (
00389 IN PVOID HeapHandle
00390 )
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 {
00403
PHEAP Heap = (
PHEAP)
HeapHandle;
00404 LIST_ENTRY ListEntry;
00405 SIZE_T
n;
00406
00407
if (
HeapHandle == NtCurrentPeb()->ProcessHeap) {
00408
00409
HeapDebugPrint((
"May not destroy the process heap at %x\n",
HeapHandle ));
00410
00411
return FALSE;
00412 }
00413
00414
if (!
RtlpCheckHeapSignature( Heap,
"RtlDestroyHeap" )) {
00415
00416
return FALSE;
00417 }
00418
00419
if (!
RtlpValidateHeap( Heap,
FALSE )) {
00420
00421
return FALSE;
00422 }
00423
00424
00425
00426
00427
00428 Heap->
Signature = 0;
00429
00430
if (Heap->
HeaderValidateCopy !=
NULL) {
00431
00432
n = 0;
00433
NtFreeVirtualMemory( NtCurrentProcess(),
00434 &Heap->
HeaderValidateCopy,
00435 &
n,
00436 MEM_RELEASE );
00437 }
00438
00439
return TRUE;
00440 }
00441
00442
00443 PVOID
00444 RtlDebugAllocateHeap (
00445 IN PVOID HeapHandle,
00446 IN ULONG Flags,
00447 IN SIZE_T Size
00448 )
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 {
00461
PHEAP Heap = (
PHEAP)
HeapHandle;
00462 BOOLEAN LockAcquired =
FALSE;
00463 PVOID ReturnValue =
NULL;
00464 SIZE_T AllocationSize;
00465
USHORT TagIndex;
00466
PHEAP_ENTRY BusyBlock;
00467
PHEAP_ENTRY_EXTRA ExtraStuff;
00468
00469
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
00470
RtlpDebugPageHeapAllocate(
HeapHandle, Flags,
Size ));
00471
00472
try {
00473
00474
try {
00475
00476
00477
00478
00479
00480
if (!
RtlpCheckHeapSignature( Heap,
"RtlAllocateHeap" )) {
00481
00482 ReturnValue =
NULL;
00483 leave;
00484 }
00485
00486 Flags |= Heap->
ForceFlags | HEAP_SETTABLE_USER_VALUE |
HEAP_SKIP_VALIDATION_CHECKS;
00487
00488
00489
00490
00491
00492 AllocationSize = (((
Size ?
Size : 1) + Heap->
AlignRound) & Heap->
AlignMask) +
00493
sizeof(
HEAP_ENTRY_EXTRA );
00494
00495
if ((AllocationSize < Size) || (AllocationSize > Heap->
MaximumAllocationSize)) {
00496
00497
HeapDebugPrint((
"Invalid allocation size - %lx (exceeded %x)\n",
00498
Size,
00499 Heap->
MaximumAllocationSize ));
00500
00501 ReturnValue =
NULL;
00502 leave;
00503 }
00504
00505
00506
00507
00508
00509
if (!(Flags & HEAP_NO_SERIALIZE)) {
00510
00511
RtlAcquireLockRoutine( Heap->
LockVariable );
00512
00513 LockAcquired =
TRUE;
00514
00515 Flags |= HEAP_NO_SERIALIZE;
00516 }
00517
00518
RtlpValidateHeap( Heap,
FALSE );
00519
00520 ReturnValue =
RtlAllocateHeapSlowly(
HeapHandle, Flags,
Size );
00521
00522
RtlpValidateHeapHeaders( Heap,
TRUE );
00523
00524
if (ReturnValue !=
NULL) {
00525
00526 BusyBlock = (
PHEAP_ENTRY)ReturnValue - 1;
00527
00528
if (BusyBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
00529
00530 ExtraStuff =
RtlpGetExtraStuffPointer( BusyBlock );
00531
00532
#if i386
00533
00534
if (Heap->
Flags &
HEAP_CAPTURE_STACK_BACKTRACES) {
00535
00536 ExtraStuff->
AllocatorBackTraceIndex = (
USHORT)RtlLogStackBackTrace();
00537
00538 }
else {
00539
00540 ExtraStuff->
AllocatorBackTraceIndex = 0;
00541 }
00542
00543
#endif // i386
00544
00545 TagIndex = ExtraStuff->
TagIndex;
00546
00547 }
else {
00548
00549 TagIndex = BusyBlock->
SmallTagIndex;
00550 }
00551
00552
if (Heap->
Flags &
HEAP_VALIDATE_ALL_ENABLED) {
00553
00554
RtlpValidateHeap( Heap,
FALSE );
00555 }
00556 }
00557
00558
if (ReturnValue !=
NULL) {
00559
00560
if ((ULONG_PTR)ReturnValue ==
RtlpHeapStopOn.
AllocAddress) {
00561
00562
HeapDebugPrint((
"Just allocated block at %lx for 0x%x bytes\n",
00563
RtlpHeapStopOn.
AllocAddress,
00564
Size ));
00565
00566
HeapDebugBreak(
NULL );
00567
00568 }
else if ((
IS_HEAP_TAGGING_ENABLED()) &&
00569 (TagIndex != 0) &&
00570 (TagIndex ==
RtlpHeapStopOn.
AllocTag.
TagIndex) &&
00571 (Heap->
ProcessHeapsListIndex ==
RtlpHeapStopOn.
AllocTag.
HeapIndex)) {
00572
00573
HeapDebugPrint((
"Just allocated block at %lx for 0x%x bytes with tag %ws\n",
00574 ReturnValue,
00575
Size,
00576
RtlpGetTagName( Heap, TagIndex )));
00577
00578
HeapDebugBreak(
NULL );
00579 }
00580 }
00581
00582 } except( GetExceptionCode() == STATUS_NO_MEMORY ?
EXCEPTION_CONTINUE_SEARCH :
00583
EXCEPTION_EXECUTE_HANDLER ) {
00584
00585
SET_LAST_STATUS( GetExceptionCode() );
00586
00587 ReturnValue =
NULL;
00588 }
00589
00590 } finally {
00591
00592
if (LockAcquired) {
00593
00594
RtlReleaseLockRoutine( Heap->
LockVariable );
00595 }
00596 }
00597
00598
return ReturnValue;
00599 }
00600
00601
00602 PVOID
00603 RtlDebugReAllocateHeap (
00604 IN PVOID HeapHandle,
00605 IN ULONG Flags,
00606 IN PVOID BaseAddress,
00607 IN SIZE_T Size
00608 )
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 {
00621
PHEAP Heap = (
PHEAP)
HeapHandle;
00622 SIZE_T AllocationSize;
00623
PHEAP_ENTRY BusyBlock;
00624
PHEAP_ENTRY_EXTRA ExtraStuff;
00625 BOOLEAN LockAcquired =
FALSE;
00626 PVOID ReturnValue =
NULL;
00627
USHORT TagIndex;
00628
00629
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
00630
RtlpDebugPageHeapReAllocate(
HeapHandle, Flags, BaseAddress,
Size ));
00631
00632
try {
00633
00634
try {
00635
00636
00637
00638
00639
00640
if (!
RtlpCheckHeapSignature( Heap,
"RtlReAllocateHeap" )) {
00641
00642 ReturnValue =
NULL;
00643 leave;
00644 }
00645
00646 Flags |= Heap->
ForceFlags | HEAP_SETTABLE_USER_VALUE |
HEAP_SKIP_VALIDATION_CHECKS;
00647
00648
00649
00650
00651
00652 AllocationSize = (((
Size ?
Size : 1) + Heap->
AlignRound) & Heap->
AlignMask) +
00653
sizeof(
HEAP_ENTRY_EXTRA );
00654
00655
if (AllocationSize < Size || AllocationSize > Heap->
MaximumAllocationSize) {
00656
00657
HeapDebugPrint((
"Invalid allocation size - %lx (exceeded %x)\n",
00658
Size,
00659 Heap->
MaximumAllocationSize ));
00660
00661
HeapDebugBreak(
NULL );
00662
00663 ReturnValue =
NULL;
00664 leave;
00665 }
00666
00667
00668
00669
00670
00671
if (!(Flags & HEAP_NO_SERIALIZE)) {
00672
00673
RtlAcquireLockRoutine( Heap->
LockVariable );
00674
00675 LockAcquired =
TRUE;
00676
00677 Flags |= HEAP_NO_SERIALIZE;
00678 }
00679
00680
RtlpValidateHeap( Heap,
FALSE );
00681 BusyBlock = (
PHEAP_ENTRY)BaseAddress - 1;
00682
00683
if (
RtlpValidateHeapEntry( Heap, BusyBlock,
"RtlReAllocateHeap" )) {
00684
00685
if ((ULONG_PTR)BaseAddress ==
RtlpHeapStopOn.
ReAllocAddress) {
00686
00687
HeapDebugPrint((
"About to reallocate block at %lx to 0x%x bytes\n",
00688
RtlpHeapStopOn.
ReAllocAddress,
00689
Size ));
00690
00691
HeapDebugBreak(
NULL );
00692
00693 }
else if (
IS_HEAP_TAGGING_ENABLED() &&
RtlpHeapStopOn.
ReAllocTag.
HeapAndTagIndex != 0) {
00694
00695
if (BusyBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
00696
00697 ExtraStuff =
RtlpGetExtraStuffPointer( BusyBlock );
00698 TagIndex = ExtraStuff->
TagIndex;
00699
00700 }
else {
00701
00702 TagIndex = BusyBlock->
SmallTagIndex;
00703 }
00704
00705
if ((TagIndex != 0) &&
00706 (TagIndex ==
RtlpHeapStopOn.
ReAllocTag.
TagIndex) &&
00707 (Heap->
ProcessHeapsListIndex ==
RtlpHeapStopOn.
ReAllocTag.
HeapIndex)) {
00708
00709
HeapDebugPrint((
"About to rellocate block at %lx to 0x%x bytes with tag %ws\n",
00710 BaseAddress,
00711
Size,
00712
RtlpGetTagName( Heap, TagIndex )));
00713
00714
HeapDebugBreak(
NULL );
00715 }
00716 }
00717
00718 ReturnValue =
RtlReAllocateHeap(
HeapHandle, Flags, BaseAddress,
Size );
00719
00720
if (ReturnValue !=
NULL) {
00721
00722 BusyBlock = (
PHEAP_ENTRY)ReturnValue - 1;
00723
00724
if (BusyBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
00725
00726 ExtraStuff =
RtlpGetExtraStuffPointer( BusyBlock );
00727
00728
#if i386
00729
00730
if (Heap->
Flags &
HEAP_CAPTURE_STACK_BACKTRACES) {
00731
00732 ExtraStuff->
AllocatorBackTraceIndex = (
USHORT)RtlLogStackBackTrace();
00733
00734 }
else {
00735
00736 ExtraStuff->
AllocatorBackTraceIndex = 0;
00737 }
00738
00739
#endif // i386
00740
00741 TagIndex = ExtraStuff->
TagIndex;
00742
00743 }
else {
00744
00745 TagIndex = BusyBlock->
SmallTagIndex;
00746 }
00747 }
00748
00749
RtlpValidateHeapHeaders( Heap,
TRUE );
00750
RtlpValidateHeap( Heap,
FALSE );
00751 }
00752
00753
if (ReturnValue !=
NULL) {
00754
00755
if ((ULONG_PTR)ReturnValue ==
RtlpHeapStopOn.
ReAllocAddress) {
00756
00757
HeapDebugPrint((
"Just reallocated block at %lx to 0x%x bytes\n",
00758
RtlpHeapStopOn.
ReAllocAddress,
00759
Size ));
00760
00761
HeapDebugBreak(
NULL );
00762
00763 }
else if ((
IS_HEAP_TAGGING_ENABLED()) &&
00764 (TagIndex ==
RtlpHeapStopOn.
ReAllocTag.
TagIndex) &&
00765 (Heap->
ProcessHeapsListIndex ==
RtlpHeapStopOn.
ReAllocTag.
HeapIndex)) {
00766
00767
HeapDebugPrint((
"Just reallocated block at %lx to 0x%x bytes with tag %ws\n",
00768 ReturnValue,
00769
Size,
00770
RtlpGetTagName( Heap, TagIndex )));
00771
00772
HeapDebugBreak(
NULL );
00773 }
00774 }
00775
00776 } except( GetExceptionCode() == STATUS_NO_MEMORY ?
EXCEPTION_CONTINUE_SEARCH :
00777
EXCEPTION_EXECUTE_HANDLER ) {
00778
00779
SET_LAST_STATUS( GetExceptionCode() );
00780
00781 ReturnValue =
NULL;
00782 }
00783
00784 } finally {
00785
00786
if (LockAcquired) {
00787
00788
RtlReleaseLockRoutine( Heap->
LockVariable );
00789 }
00790 }
00791
00792
return ReturnValue;
00793 }
00794
00795
00796 BOOLEAN
00797 RtlDebugFreeHeap (
00798 IN PVOID HeapHandle,
00799 IN ULONG Flags,
00800 IN PVOID BaseAddress
00801 )
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813 {
00814
PHEAP Heap = (
PHEAP)
HeapHandle;
00815
PHEAP_ENTRY BusyBlock;
00816
PHEAP_ENTRY_EXTRA ExtraStuff;
00817 SIZE_T
Size;
00818 BOOLEAN Result =
FALSE;
00819 BOOLEAN LockAcquired =
FALSE;
00820
USHORT TagIndex;
00821
00822
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
00823
RtlpDebugPageHeapFree(
HeapHandle, Flags, BaseAddress ));
00824
00825
try {
00826
00827
try {
00828
00829
00830
00831
00832
00833
if (!
RtlpCheckHeapSignature( Heap,
"RtlFreeHeap" )) {
00834
00835 Result =
FALSE;
00836 leave;
00837 }
00838
00839 Flags |= Heap->
ForceFlags |
HEAP_SKIP_VALIDATION_CHECKS;
00840
00841
00842
00843
00844
00845
if (!(Flags & HEAP_NO_SERIALIZE)) {
00846
00847
RtlAcquireLockRoutine( Heap->
LockVariable );
00848
00849 LockAcquired =
TRUE;
00850
00851 Flags |= HEAP_NO_SERIALIZE;
00852 }
00853
00854
RtlpValidateHeap( Heap,
FALSE );
00855
00856 BusyBlock = (
PHEAP_ENTRY)BaseAddress - 1;
00857
Size = BusyBlock->
Size <<
HEAP_GRANULARITY_SHIFT;
00858
00859
if (
RtlpValidateHeapEntry( Heap, BusyBlock,
"RtlFreeHeap" )) {
00860
00861
if ((ULONG_PTR)BaseAddress ==
RtlpHeapStopOn.
FreeAddress) {
00862
00863
HeapDebugPrint((
"About to free block at %lx\n",
00864
RtlpHeapStopOn.
FreeAddress ));
00865
00866
HeapDebugBreak(
NULL );
00867
00868 }
else if ((
IS_HEAP_TAGGING_ENABLED()) && (
RtlpHeapStopOn.
FreeTag.
HeapAndTagIndex != 0)) {
00869
00870
if (BusyBlock->
Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
00871
00872 ExtraStuff =
RtlpGetExtraStuffPointer( BusyBlock );
00873
00874 TagIndex = ExtraStuff->
TagIndex;
00875
00876 }
else {
00877
00878 TagIndex = BusyBlock->
SmallTagIndex;
00879 }
00880
00881
if ((TagIndex != 0) &&
00882 (TagIndex ==
RtlpHeapStopOn.
FreeTag.
TagIndex) &&
00883 (Heap->
ProcessHeapsListIndex ==
RtlpHeapStopOn.
FreeTag.
HeapIndex)) {
00884
00885
HeapDebugPrint((
"About to free block at %lx with tag %ws\n",
00886 BaseAddress,
00887
RtlpGetTagName( Heap, TagIndex )));
00888
00889
HeapDebugBreak(
NULL );
00890 }
00891 }
00892
00893 Result =
RtlFreeHeapSlowly(
HeapHandle, Flags, BaseAddress );
00894
00895
RtlpValidateHeapHeaders( Heap,
TRUE );
00896
RtlpValidateHeap( Heap,
FALSE );
00897 }
00898
00899 } except(
EXCEPTION_EXECUTE_HANDLER ) {
00900
00901
SET_LAST_STATUS( GetExceptionCode() );
00902
00903 Result =
FALSE;
00904 }
00905
00906 } finally {
00907
00908
if (LockAcquired) {
00909
00910
RtlReleaseLockRoutine( Heap->
LockVariable );
00911 }
00912 }
00913
00914
return Result;
00915 }
00916
00917
00918 BOOLEAN
00919 RtlDebugGetUserInfoHeap (
00920 IN PVOID HeapHandle,
00921 IN ULONG Flags,
00922 IN PVOID BaseAddress,
00923 OUT PVOID *UserValue OPTIONAL,
00924 OUT PULONG UserFlags OPTIONAL
00925 )
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 {
00938
PHEAP Heap = (
PHEAP)
HeapHandle;
00939
PHEAP_ENTRY BusyBlock;
00940 BOOLEAN Result =
FALSE;
00941 BOOLEAN LockAcquired =
FALSE;
00942
00943
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
00944
RtlpDebugPageHeapGetUserInfo(
HeapHandle, Flags, BaseAddress, UserValue, UserFlags ));
00945
00946
try {
00947
00948
try {
00949
00950
00951
00952
00953
00954
if (!
RtlpCheckHeapSignature( Heap,
"RtlGetUserInfoHeap" )) {
00955
00956 Result =
FALSE;
00957 leave;
00958 }
00959
00960 Flags |= Heap->
ForceFlags |
HEAP_SKIP_VALIDATION_CHECKS;
00961
00962
00963
00964
00965
00966
if (!(Flags & HEAP_NO_SERIALIZE)) {
00967
00968
RtlAcquireLockRoutine( Heap->
LockVariable );
00969
00970 LockAcquired =
TRUE;
00971
00972 Flags |= HEAP_NO_SERIALIZE;
00973 }
00974
00975
RtlpValidateHeap( Heap,
FALSE );
00976
00977 BusyBlock = (
PHEAP_ENTRY)BaseAddress - 1;
00978
00979
if (
RtlpValidateHeapEntry( Heap, BusyBlock,
"RtlGetUserInfoHeap" )) {
00980
00981 Result =
RtlGetUserInfoHeap(
HeapHandle, Flags, BaseAddress, UserValue, UserFlags );
00982 }
00983
00984 } except(
EXCEPTION_EXECUTE_HANDLER ) {
00985
00986
SET_LAST_STATUS( GetExceptionCode() );
00987 }
00988
00989 } finally {
00990
00991
if (LockAcquired) {
00992
00993
RtlReleaseLockRoutine( Heap->
LockVariable );
00994 }
00995 }
00996
00997
return Result;
00998 }
00999
01000
01001 BOOLEAN
01002 RtlDebugSetUserValueHeap (
01003 IN PVOID HeapHandle,
01004 IN ULONG Flags,
01005 IN PVOID BaseAddress,
01006 IN PVOID UserValue
01007 )
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 {
01020
PHEAP Heap = (
PHEAP)
HeapHandle;
01021
PHEAP_ENTRY BusyBlock;
01022 BOOLEAN Result =
FALSE;
01023 BOOLEAN LockAcquired =
FALSE;
01024
01025
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
01026
RtlpDebugPageHeapSetUserValue(
HeapHandle, Flags, BaseAddress, UserValue ));
01027
01028
try {
01029
01030
try {
01031
01032
01033
01034
01035
01036
if (!
RtlpCheckHeapSignature( Heap,
"RtlSetUserValueHeap" )) {
01037
01038 Result =
FALSE;
01039 leave;
01040 }
01041
01042 Flags |= Heap->
ForceFlags |
HEAP_SKIP_VALIDATION_CHECKS;
01043
01044
01045
01046
01047
01048
if (!(Flags & HEAP_NO_SERIALIZE)) {
01049
01050
RtlAcquireLockRoutine( Heap->
LockVariable );
01051
01052 LockAcquired =
TRUE;
01053
01054 Flags |= HEAP_NO_SERIALIZE;
01055 }
01056
01057
RtlpValidateHeap( Heap,
FALSE );
01058
01059 BusyBlock = (
PHEAP_ENTRY)BaseAddress - 1;
01060
01061
if (
RtlpValidateHeapEntry( Heap, BusyBlock,
"RtlSetUserValueHeap" )) {
01062
01063 Result =
RtlSetUserValueHeap(
HeapHandle, Flags, BaseAddress, UserValue );
01064
01065
RtlpValidateHeap( Heap,
FALSE );
01066 }
01067
01068 } except(
EXCEPTION_EXECUTE_HANDLER ) {
01069
01070
SET_LAST_STATUS( GetExceptionCode() );
01071 }
01072
01073 } finally {
01074
01075
if (LockAcquired) {
01076
01077
RtlReleaseLockRoutine( Heap->
LockVariable );
01078 }
01079 }
01080
01081
return Result;
01082 }
01083
01084
01085 BOOLEAN
01086 RtlDebugSetUserFlagsHeap (
01087 IN PVOID HeapHandle,
01088 IN ULONG Flags,
01089 IN PVOID BaseAddress,
01090 IN ULONG UserFlagsReset,
01091 IN ULONG UserFlagsSet
01092 )
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104 {
01105
PHEAP Heap = (
PHEAP)
HeapHandle;
01106
PHEAP_ENTRY BusyBlock;
01107 BOOLEAN Result =
FALSE;
01108 BOOLEAN LockAcquired =
FALSE;
01109
01110
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
01111
RtlpDebugPageHeapSetUserFlags(
HeapHandle, Flags, BaseAddress, UserFlagsReset, UserFlagsSet ));
01112
01113
if ((UserFlagsReset & ~HEAP_SETTABLE_USER_FLAGS) ||
01114 (UserFlagsSet & ~HEAP_SETTABLE_USER_FLAGS)) {
01115
01116
return FALSE;
01117 }
01118
01119
try {
01120
01121
try {
01122
01123
01124
01125
01126
01127
if (!
RtlpCheckHeapSignature( Heap,
"RtlSetUserFlagsHeap" )) {
01128
01129 Result =
FALSE;
01130 leave;
01131 }
01132
01133 Flags |= Heap->
ForceFlags |
HEAP_SKIP_VALIDATION_CHECKS;
01134
01135
01136
01137
01138
01139
if (!(Flags & HEAP_NO_SERIALIZE)) {
01140
01141
RtlAcquireLockRoutine( Heap->
LockVariable );
01142
01143 LockAcquired =
TRUE;
01144
01145 Flags |= HEAP_NO_SERIALIZE;
01146 }
01147
01148
RtlpValidateHeap( Heap,
FALSE );
01149
01150 BusyBlock = (
PHEAP_ENTRY)BaseAddress - 1;
01151
01152
if (
RtlpValidateHeapEntry( Heap, BusyBlock,
"RtlSetUserFlagsHeap" )) {
01153
01154 Result =
RtlSetUserFlagsHeap(
HeapHandle, Flags, BaseAddress, UserFlagsReset, UserFlagsSet );
01155
01156
RtlpValidateHeap( Heap,
FALSE );
01157 }
01158
01159 } except(
EXCEPTION_EXECUTE_HANDLER ) {
01160
01161
SET_LAST_STATUS( GetExceptionCode() );
01162 }
01163
01164 } finally {
01165
01166
if (LockAcquired) {
01167
01168
RtlReleaseLockRoutine( Heap->
LockVariable );
01169 }
01170 }
01171
01172
return Result;
01173 }
01174
01175
01176 SIZE_T
01177 RtlDebugSizeHeap (
01178 IN PVOID HeapHandle,
01179 IN ULONG Flags,
01180 IN PVOID BaseAddress
01181 )
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193 {
01194
PHEAP Heap = (
PHEAP)
HeapHandle;
01195
PHEAP_ENTRY BusyBlock;
01196 BOOLEAN LockAcquired =
FALSE;
01197 SIZE_T BusySize;
01198
01199
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
01200
RtlpDebugPageHeapSize(
HeapHandle, Flags, BaseAddress ));
01201
01202 BusySize = 0xFFFFFFFF;
01203
01204
try {
01205
01206
try {
01207
01208
01209
01210
01211
01212
if (!
RtlpCheckHeapSignature( Heap,
"RtlSizeHeap" )) {
01213
01214 BusySize =
FALSE;
01215 leave;
01216 }
01217
01218 Flags |= Heap->
ForceFlags |
HEAP_SKIP_VALIDATION_CHECKS;
01219
01220
01221
01222
01223
01224
if (!(Flags & HEAP_NO_SERIALIZE)) {
01225
01226
RtlAcquireLockRoutine( Heap->
LockVariable );
01227
01228 Flags |= HEAP_NO_SERIALIZE;
01229
01230 LockAcquired =
TRUE;
01231 }
01232
01233
RtlpValidateHeap( Heap,
FALSE );
01234
01235 BusyBlock = (
PHEAP_ENTRY)BaseAddress - 1;
01236
01237
if (
RtlpValidateHeapEntry( Heap, BusyBlock,
"RtlSizeHeap" )) {
01238
01239 BusySize =
RtlSizeHeap(
HeapHandle, Flags, BaseAddress );
01240 }
01241
01242 } except(
EXCEPTION_EXECUTE_HANDLER ) {
01243
01244
SET_LAST_STATUS( GetExceptionCode() );
01245 }
01246
01247 } finally {
01248
01249
if (LockAcquired) {
01250
01251
RtlReleaseLockRoutine( Heap->
LockVariable );
01252 }
01253 }
01254
01255
return BusySize;
01256 }
01257
01258
01259 SIZE_T
01260 RtlDebugCompactHeap (
01261 IN PVOID HeapHandle,
01262 IN ULONG Flags
01263 )
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275 {
01276
PHEAP Heap = (
PHEAP)
HeapHandle;
01277 BOOLEAN LockAcquired =
FALSE;
01278 SIZE_T LargestFreeSize;
01279
01280
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
01281
RtlpDebugPageHeapCompact(
HeapHandle, Flags ));
01282
01283 LargestFreeSize = 0;
01284
01285
try {
01286
01287
try {
01288
01289
01290
01291
01292
01293
if (!
RtlpCheckHeapSignature( Heap,
"RtlCompactHeap" )) {
01294
01295 LargestFreeSize = 0;
01296 leave;
01297 }
01298
01299 Flags |= Heap->
ForceFlags |
HEAP_SKIP_VALIDATION_CHECKS;
01300
01301
01302
01303
01304
01305
if (!(Flags & HEAP_NO_SERIALIZE)) {
01306
01307
RtlAcquireLockRoutine( Heap->
LockVariable );
01308
01309 LockAcquired =
TRUE;
01310
01311 Flags |= HEAP_NO_SERIALIZE;
01312 }
01313
01314
RtlpValidateHeap( Heap,
FALSE );
01315
01316 LargestFreeSize =
RtlCompactHeap(
HeapHandle, Flags );
01317
01318
RtlpValidateHeapHeaders( Heap,
TRUE );
01319
01320 } except(
EXCEPTION_EXECUTE_HANDLER ) {
01321
01322
SET_LAST_STATUS( GetExceptionCode() );
01323 }
01324
01325 } finally {
01326
01327
if (LockAcquired) {
01328
01329
RtlReleaseLockRoutine( Heap->
LockVariable );
01330 }
01331 }
01332
01333
return LargestFreeSize;
01334 }
01335
01336
01337
NTSTATUS
01338 RtlDebugZeroHeap (
01339 IN PVOID HeapHandle,
01340 IN ULONG Flags
01341 )
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353 {
01354
NTSTATUS Status;
01355
PHEAP Heap = (
PHEAP)
HeapHandle;
01356 BOOLEAN LockAcquired =
FALSE;
01357 SIZE_T LargestFreeSize;
01358
01359
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
01360
RtlpDebugPageHeapZero(
HeapHandle, Flags ));
01361
01362
Status = STATUS_SUCCESS;
01363 LargestFreeSize = 0;
01364
01365
try {
01366
01367
try {
01368
01369
01370
01371
01372
01373
if (!
RtlpCheckHeapSignature( Heap,
"RtlZeroHeap" )) {
01374
01375
Status = STATUS_INVALID_PARAMETER;
01376 leave;
01377 }
01378
01379 Flags |= Heap->
ForceFlags |
HEAP_SKIP_VALIDATION_CHECKS;
01380
01381
01382
01383
01384
01385
if (!(Flags & HEAP_NO_SERIALIZE)) {
01386
01387
RtlAcquireLockRoutine( Heap->
LockVariable );
01388
01389 LockAcquired =
TRUE;
01390
01391 Flags |= HEAP_NO_SERIALIZE;
01392 }
01393
01394
if (!
RtlpValidateHeap( Heap,
FALSE )) {
01395
01396
Status = STATUS_INVALID_PARAMETER;
01397
01398 }
else {
01399
01400
Status =
RtlZeroHeap(
HeapHandle, Flags );
01401 }
01402
01403 } except(
EXCEPTION_EXECUTE_HANDLER ) {
01404
01405
Status = GetExceptionCode();
01406 }
01407
01408 } finally {
01409
01410
if (LockAcquired) {
01411
01412
RtlReleaseLockRoutine( Heap->
LockVariable );
01413 }
01414 }
01415
01416
return Status;
01417 }
01418
01419
01420
NTSTATUS
01421 RtlDebugCreateTagHeap (
01422 IN PVOID HeapHandle,
01423 IN ULONG Flags,
01424 IN PWSTR TagPrefix OPTIONAL,
01425 IN PWSTR TagNames
01426 )
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438 {
01439
PHEAP Heap = (
PHEAP)
HeapHandle;
01440 BOOLEAN LockAcquired =
FALSE;
01441 ULONG TagIndex;
01442
01443 TagIndex = 0;
01444
01445
try {
01446
01447
try {
01448
01449
01450
01451
01452
01453
if (
RtlpCheckHeapSignature( Heap,
"RtlCreateTagHeap" )) {
01454
01455 Flags |= Heap->
ForceFlags |
HEAP_SKIP_VALIDATION_CHECKS;
01456
01457
01458
01459
01460
01461
if (!(Flags & HEAP_NO_SERIALIZE)) {
01462
01463
RtlAcquireLockRoutine( Heap->
LockVariable );
01464
01465 LockAcquired =
TRUE;
01466
01467 Flags |= HEAP_NO_SERIALIZE;
01468 }
01469
01470
if (
RtlpValidateHeap( Heap,
FALSE )) {
01471
01472 TagIndex =
RtlCreateTagHeap(
HeapHandle, Flags, TagPrefix, TagNames );
01473 }
01474
01475
RtlpValidateHeapHeaders( Heap,
TRUE );
01476 }
01477
01478 } except(
EXCEPTION_EXECUTE_HANDLER ) {
01479
01480
SET_LAST_STATUS( GetExceptionCode() );
01481 }
01482
01483 } finally {
01484
01485
if (LockAcquired) {
01486
01487
RtlReleaseLockRoutine( Heap->
LockVariable );
01488 }
01489 }
01490
01491
return TagIndex;
01492 }
01493
01494
01495 NTSYSAPI
01496 PWSTR
01497 NTAPI
01498 RtlDebugQueryTagHeap (
01499 IN PVOID HeapHandle,
01500 IN ULONG Flags,
01501 IN USHORT TagIndex,
01502 IN BOOLEAN ResetCounters,
01503 OUT PRTL_HEAP_TAG_INFO TagInfo OPTIONAL
01504 )
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516 {
01517
PHEAP Heap = (
PHEAP)
HeapHandle;
01518 BOOLEAN LockAcquired =
FALSE;
01519 PWSTR Result;
01520
01521 Result =
NULL;
01522
01523
try {
01524
01525
try {
01526
01527
01528
01529
01530
01531
if (
RtlpCheckHeapSignature( Heap,
"RtlQueryTagHeap" )) {
01532
01533 Flags |= Heap->
ForceFlags |
HEAP_SKIP_VALIDATION_CHECKS;
01534
01535
01536
01537
01538
01539
if (!(Flags & HEAP_NO_SERIALIZE)) {
01540
01541
RtlAcquireLockRoutine( Heap->
LockVariable );
01542
01543 LockAcquired =
TRUE;
01544
01545 Flags |= HEAP_NO_SERIALIZE;
01546 }
01547
01548
if (
RtlpValidateHeap( Heap,
FALSE )) {
01549
01550 Result =
RtlQueryTagHeap(
HeapHandle, Flags, TagIndex, ResetCounters, TagInfo );
01551 }
01552 }
01553
01554 } except(
EXCEPTION_EXECUTE_HANDLER ) {
01555
01556
SET_LAST_STATUS( GetExceptionCode() );
01557 }
01558
01559 } finally {
01560
01561
if (LockAcquired) {
01562
01563
RtlReleaseLockRoutine( Heap->
LockVariable );
01564 }
01565 }
01566
01567
return Result;
01568 }
01569
01570
01571
NTSTATUS
01572 RtlDebugUsageHeap (
01573 IN PVOID HeapHandle,
01574 IN ULONG Flags,
01575 IN OUT PRTL_HEAP_USAGE Usage
01576 )
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588 {
01589
PHEAP Heap = (
PHEAP)
HeapHandle;
01590
NTSTATUS Status;
01591 BOOLEAN LockAcquired =
FALSE;
01592
01593
IF_DEBUG_PAGE_HEAP_THEN_RETURN(
HeapHandle,
01594
RtlpDebugPageHeapUsage(
HeapHandle, Flags,
Usage ));
01595
01596
Status = STATUS_SUCCESS;
01597
01598
try {
01599
01600
try {
01601
01602
01603
01604
01605
01606
if (!
RtlpCheckHeapSignature( Heap,
"RtlUsageHeap" )) {
01607
01608
Status = STATUS_INVALID_PARAMETER;
01609 leave;
01610 }
01611
01612 Flags |= Heap->
ForceFlags |
HEAP_SKIP_VALIDATION_CHECKS;
01613
01614
01615
01616
01617
01618
if (!(Flags & HEAP_NO_SERIALIZE)) {
01619
01620
RtlAcquireLockRoutine( Heap->
LockVariable );
01621
01622 LockAcquired =
TRUE;
01623
01624 Flags |= HEAP_NO_SERIALIZE;
01625 }
01626
01627
if (!
RtlpValidateHeap( Heap,
FALSE )) {
01628
01629
Status = STATUS_INVALID_PARAMETER;
01630
01631 }
else {
01632
01633
Status =
RtlUsageHeap(
HeapHandle, Flags,
Usage );
01634 }
01635
01636 } except(
EXCEPTION_EXECUTE_HANDLER ) {
01637
01638
Status = GetExceptionCode();
01639 }
01640
01641 } finally {
01642
01643
if (LockAcquired) {
01644
01645
RtlReleaseLockRoutine( Heap->
LockVariable );
01646 }
01647 }
01648
01649
return Status;
01650 }
01651
01652
01653 BOOLEAN
01654 RtlDebugWalkHeap (
01655 IN PVOID HeapHandle,
01656 IN OUT PRTL_HEAP_WALK_ENTRY Entry
01657 )
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669 {
01670
PHEAP Heap = (
PHEAP)
HeapHandle;
01671 BOOLEAN Result;
01672
01673
01674
01675
01676
01677 Result =
FALSE;
01678
01679
try {
01680
01681
if (
RtlpCheckHeapSignature( Heap,
"RtlWalkHeap" )) {
01682
01683 Result =
RtlpValidateHeap( Heap,
FALSE );
01684 }
01685
01686 } except(
EXCEPTION_EXECUTE_HANDLER ) {
01687
01688
SET_LAST_STATUS( GetExceptionCode() );
01689 }
01690
01691
return Result;
01692 }
01693
01694
01695 BOOLEAN
01696 RtlpValidateHeapEntry (
01697 IN
PHEAP Heap,
01698 IN
PHEAP_ENTRY BusyBlock,
01699 IN PCHAR Reason
01700 )
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712 {
01713
PHEAP_SEGMENT Segment;
01714 UCHAR SegmentIndex;
01715 BOOLEAN Result;
01716
01717
if ((BusyBlock ==
NULL)
01718
01719 ||
01720
01721 ((ULONG_PTR)BusyBlock & (
HEAP_GRANULARITY-1))
01722
01723 ||
01724
01725 ((BusyBlock->Flags &
HEAP_ENTRY_VIRTUAL_ALLOC) &&
01726 ((ULONG_PTR)BusyBlock & (
PAGE_SIZE-1)) != FIELD_OFFSET(
HEAP_VIRTUAL_ALLOC_ENTRY, BusyBlock ))
01727
01728 ||
01729
01730 (!(BusyBlock->Flags &
HEAP_ENTRY_VIRTUAL_ALLOC) &&
01731 ((BusyBlock->SegmentIndex >=
HEAP_MAXIMUM_SEGMENTS) ||
01732 !(Segment = Heap->Segments[ BusyBlock->SegmentIndex ]) ||
01733 (BusyBlock < Segment->
FirstEntry) ||
01734 (BusyBlock >= Segment->
LastValidEntry)))
01735
01736 ||
01737
01738 !(BusyBlock->Flags &
HEAP_ENTRY_BUSY)
01739
01740 ||
01741
01742 ((BusyBlock->Flags &
HEAP_ENTRY_FILL_PATTERN) && !
RtlpCheckBusyBlockTail( BusyBlock ))) {
01743
01744 InvalidBlock:
01745
01746
HeapDebugPrint((
"Invalid Address specified to %s( %lx, %lx )\n",
01747 Reason,
01748 Heap,
01749 BusyBlock + 1 ));
01750
01751
HeapDebugBreak( BusyBlock );
01752
01753
return FALSE;
01754
01755 }
else {
01756
01757
if (BusyBlock->Flags &
HEAP_ENTRY_VIRTUAL_ALLOC) {
01758
01759 Result =
TRUE;
01760
01761 }
else {
01762
01763
for (SegmentIndex=0; SegmentIndex<
HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) {
01764
01765 Segment = Heap->Segments[ SegmentIndex ];
01766
01767
if (Segment) {
01768
01769
if ((BusyBlock >= Segment->
FirstEntry) &&
01770 (BusyBlock < Segment->
LastValidEntry)) {
01771
01772 Result =
TRUE;
01773
break;
01774 }
01775 }
01776 }
01777 }
01778
01779
if (!Result) {
01780
01781
goto InvalidBlock;
01782 }
01783
01784
return TRUE;
01785 }
01786 }
01787
01788
01789 BOOLEAN
01790 RtlpValidateHeapSegment (
01791 IN
PHEAP Heap,
01792 IN
PHEAP_SEGMENT Segment,
01793 IN UCHAR SegmentIndex,
01794 IN OUT PULONG CountOfFreeBlocks,
01795 IN OUT PSIZE_T TotalFreeSize,
01796 OUT PVOID *BadAddress,
01797 IN OUT PSIZE_T ComputedTagEntries,
01798 IN OUT PSIZE_T ComputedPseudoTagEntries
01799 )
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811 {
01812
PHEAP_ENTRY CurrentBlock, PreviousBlock;
01813 SIZE_T
Size;
01814
USHORT PreviousSize, TagIndex;
01815
PHEAP_UNCOMMMTTED_RANGE UnCommittedRange;
01816
PHEAP_ENTRY_EXTRA ExtraStuff;
01817 ULONG NumberOfUnCommittedPages;
01818 ULONG NumberOfUnCommittedRanges;
01819
01820
RTL_PAGED_CODE();
01821
01822 NumberOfUnCommittedPages = 0;
01823 NumberOfUnCommittedRanges = 0;
01824
01825 UnCommittedRange = Segment->UnCommittedRanges;
01826
01827
if (Segment->BaseAddress == Heap) {
01828
01829 CurrentBlock = &Heap->Entry;
01830
01831 }
else {
01832
01833 CurrentBlock = &Segment->Entry;
01834 }
01835
01836
while (CurrentBlock < Segment->LastValidEntry) {
01837
01838 *BadAddress = CurrentBlock;
01839
01840
if ((UnCommittedRange !=
NULL) &&
01841 ((ULONG_PTR)CurrentBlock >= UnCommittedRange->
Address)) {
01842
01843
HeapDebugPrint((
"Heap entry %lx is beyond uncommited range [%x .. %x)\n",
01844 CurrentBlock,
01845 UnCommittedRange->
Address,
01846 (PCHAR)UnCommittedRange->
Address + UnCommittedRange->
Size ));
01847
01848
return FALSE;
01849 }
01850
01851 PreviousSize = 0;
01852
01853
while (CurrentBlock < Segment->LastValidEntry) {
01854
01855 *BadAddress = CurrentBlock;
01856
01857
if (PreviousSize != CurrentBlock->PreviousSize) {
01858
01859
HeapDebugPrint((
"Heap entry %lx has incorrect PreviousSize field (%04x instead of %04x)\n",
01860 CurrentBlock, CurrentBlock->PreviousSize, PreviousSize ));
01861
01862
return FALSE;
01863 }
01864
01865 PreviousSize = CurrentBlock->Size;
01866
Size = (ULONG_PTR)CurrentBlock->Size <<
HEAP_GRANULARITY_SHIFT;
01867
01868
if (CurrentBlock->Flags &
HEAP_ENTRY_BUSY) {
01869
01870
if (ComputedTagEntries !=
NULL) {
01871
01872
if (CurrentBlock->Flags &
HEAP_ENTRY_EXTRA_PRESENT) {
01873
01874 ExtraStuff =
RtlpGetExtraStuffPointer( CurrentBlock );
01875 TagIndex = ExtraStuff->
TagIndex;
01876
01877 }
else {
01878
01879 TagIndex = CurrentBlock->SmallTagIndex;
01880 }
01881
01882
if (TagIndex != 0) {
01883
01884
if (TagIndex & HEAP_PSEUDO_TAG_FLAG) {
01885
01886 TagIndex &= ~HEAP_PSEUDO_TAG_FLAG;
01887
01888
if (TagIndex <
HEAP_NUMBER_OF_PSEUDO_TAG) {
01889
01890 ComputedPseudoTagEntries[ TagIndex ] += CurrentBlock->Size;
01891 }
01892
01893 }
else if (TagIndex & HEAP_GLOBAL_TAG) {
01894
01895
01896
01897
01898
01899
01900 }
else if (TagIndex < Heap->NextAvailableTagIndex) {
01901
01902 ComputedTagEntries[ TagIndex ] += CurrentBlock->Size;
01903 }
01904 }
01905 }
01906
01907
if (CurrentBlock->Flags &
HEAP_ENTRY_FILL_PATTERN) {
01908
01909
if (!
RtlpCheckBusyBlockTail( CurrentBlock )) {
01910
01911
return FALSE;
01912 }
01913 }
01914
01915 }
else {
01916
01917 *CountOfFreeBlocks += 1;
01918 *TotalFreeSize += CurrentBlock->Size;
01919
01920
if ((Heap->Flags & HEAP_FREE_CHECKING_ENABLED) &&
01921 (CurrentBlock->Flags &
HEAP_ENTRY_FILL_PATTERN)) {
01922
01923 SIZE_T cb, cbEqual;
01924
01925 cb =
Size -
sizeof(
HEAP_FREE_ENTRY );
01926
01927
if ((CurrentBlock->Flags &
HEAP_ENTRY_EXTRA_PRESENT) &&
01928 (cb >
sizeof(
HEAP_FREE_ENTRY_EXTRA ))) {
01929
01930 cb -=
sizeof(
HEAP_FREE_ENTRY_EXTRA );
01931 }
01932
01933 cbEqual =
RtlCompareMemoryUlong( (PCHAR)((
PHEAP_FREE_ENTRY)CurrentBlock + 1),
01934 cb,
01935
FREE_HEAP_FILL );
01936
01937
if (cbEqual != cb) {
01938
01939
HeapDebugPrint((
"Free Heap block %lx modified at %lx after it was freed\n",
01940 CurrentBlock,
01941 (PCHAR)(CurrentBlock + 1) + cbEqual ));
01942
01943
return FALSE;
01944 }
01945 }
01946 }
01947
01948
if (CurrentBlock->SegmentIndex != SegmentIndex) {
01949
01950
HeapDebugPrint((
"Heap block at %lx has incorrect segment index (%x)\n",
01951 CurrentBlock,
01952 SegmentIndex ));
01953
01954
return FALSE;
01955 }
01956
01957
if (CurrentBlock->Flags &
HEAP_ENTRY_LAST_ENTRY) {
01958
01959 CurrentBlock = (
PHEAP_ENTRY)((PCHAR)CurrentBlock +
Size);
01960
01961
if (UnCommittedRange ==
NULL) {
01962
01963
if (CurrentBlock != Segment->LastValidEntry) {
01964
01965
HeapDebugPrint((
"Heap block at %lx is not last block in segment (%x)\n",
01966 CurrentBlock,
01967 Segment->LastValidEntry ));
01968
01969
return FALSE;
01970 }
01971
01972 }
else if ((ULONG_PTR)CurrentBlock != UnCommittedRange->
Address) {
01973
01974
HeapDebugPrint((
"Heap block at %lx does not match address of next uncommitted address (%x)\n",
01975 CurrentBlock,
01976 UnCommittedRange->
Address ));
01977
01978
return FALSE;
01979
01980 }
else {
01981
01982 NumberOfUnCommittedPages += (ULONG) (UnCommittedRange->
Size /
PAGE_SIZE);
01983 NumberOfUnCommittedRanges += 1;
01984
01985 CurrentBlock = (
PHEAP_ENTRY)
01986 ((PCHAR)UnCommittedRange->
Address + UnCommittedRange->
Size);
01987
01988 UnCommittedRange = UnCommittedRange->
Next;
01989 }
01990
01991
break;
01992 }
01993
01994 CurrentBlock = (
PHEAP_ENTRY)((PCHAR)CurrentBlock +
Size);
01995 }
01996 }
01997
01998 *BadAddress = Segment;
01999
02000
if (Segment->NumberOfUnCommittedPages != NumberOfUnCommittedPages) {
02001
02002
HeapDebugPrint((
"Heap Segment at %lx contains invalid NumberOfUnCommittedPages (%x != %x)\n",
02003 Segment,
02004 Segment->NumberOfUnCommittedPages,
02005 NumberOfUnCommittedPages ));
02006
02007
return FALSE;
02008 }
02009
02010
if (Segment->NumberOfUnCommittedRanges != NumberOfUnCommittedRanges) {
02011
02012
HeapDebugPrint((
"Heap Segment at %lx contains invalid NumberOfUnCommittedRanges (%x != %x)\n",
02013 Segment,
02014 Segment->NumberOfUnCommittedRanges,
02015 NumberOfUnCommittedRanges ));
02016
02017
return FALSE;
02018 }
02019
02020
return TRUE;
02021 }
02022
02023
02024 BOOLEAN
02025 RtlpValidateHeap (
02026 IN
PHEAP Heap,
02027 IN BOOLEAN AlwaysValidate
02028 )
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040 {
02041
NTSTATUS Status;
02042
PHEAP_SEGMENT Segment;
02043 PLIST_ENTRY Head, Next;
02044
PHEAP_FREE_ENTRY FreeBlock;
02045 BOOLEAN EmptyFreeList;
02046 ULONG NumberOfFreeListEntries;
02047 ULONG CountOfFreeBlocks;
02048 SIZE_T TotalFreeSize;
02049 SIZE_T
Size;
02050
USHORT PreviousSize;
02051 UCHAR SegmentIndex;
02052 PVOID BadAddress;
02053 PSIZE_T ComputedTagEntries =
NULL;
02054 PSIZE_T ComputedPseudoTagEntries =
NULL;
02055
PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock;
02056
USHORT TagIndex;
02057
02058
RTL_PAGED_CODE();
02059
02060 BadAddress = Heap;
02061
02062
if (!
RtlpValidateHeapHeaders( Heap,
FALSE )) {
02063
02064
goto errorExit;
02065 }
02066
02067
if (!AlwaysValidate && !(Heap->Flags &
HEAP_VALIDATE_ALL_ENABLED)) {
02068
02069
goto exit;
02070 }
02071
02072 NumberOfFreeListEntries = 0;
02073 Head = &Heap->FreeLists[ 0 ];
02074
02075
for (
Size = 0;
Size <
HEAP_MAXIMUM_FREELISTS;
Size++) {
02076
02077
if (
Size != 0) {
02078
02079 EmptyFreeList = (BOOLEAN)(IsListEmpty( Head ));
02080 BadAddress = &Heap->u.FreeListsInUseBytes[
Size / 8 ];
02081
02082
if (Heap->u.FreeListsInUseBytes[
Size / 8 ] & (1 << (
Size & 7)) ) {
02083
02084
if (EmptyFreeList) {
02085
02086
HeapDebugPrint((
"dedicated (%04x) free list empty but marked as non-empty\n",
02087
Size ));
02088
02089
goto errorExit;
02090 }
02091
02092 }
else {
02093
02094
if (!EmptyFreeList) {
02095
02096
HeapDebugPrint((
"dedicated (%04x) free list non-empty but marked as empty\n",
02097
Size ));
02098
02099
goto errorExit;
02100 }
02101 }
02102 }
02103
02104 Next = Head->Flink;
02105 PreviousSize = 0;
02106
02107
while (Head != Next) {
02108
02109 FreeBlock = CONTAINING_RECORD( Next,
HEAP_FREE_ENTRY, FreeList );
02110 Next = Next->Flink;
02111
02112 BadAddress = FreeBlock;
02113
02114
if (FreeBlock->Flags &
HEAP_ENTRY_BUSY) {
02115
02116
HeapDebugPrint((
"dedicated (%04x) free list element %lx is marked busy\n",
02117
Size,
02118 FreeBlock ));
02119
02120
goto errorExit;
02121 }
02122
02123
if ((
Size != 0) && (FreeBlock->Size !=
Size)) {
02124
02125
HeapDebugPrint((
"Dedicated (%04x) free list element %lx is wrong size (%04x)\n",
02126
Size,
02127 FreeBlock,
02128 FreeBlock->Size ));
02129
02130
goto errorExit;
02131
02132 }
else if ((
Size == 0) && (FreeBlock->Size <
HEAP_MAXIMUM_FREELISTS)) {
02133
02134
HeapDebugPrint((
"Non-Dedicated free list element %lx with too small size (%04x)\n",
02135 FreeBlock,
02136 FreeBlock->Size ));
02137
02138
goto errorExit;
02139
02140 }
else if ((
Size == 0) && (FreeBlock->Size < PreviousSize)) {
02141
02142
HeapDebugPrint((
"Non-Dedicated free list element %lx is out of order\n",
02143 FreeBlock ));
02144
02145
goto errorExit;
02146
02147 }
else {
02148
02149 PreviousSize = FreeBlock->Size;
02150 }
02151
02152 NumberOfFreeListEntries++;
02153 }
02154
02155 Head++;
02156 }
02157
02158
Size = (
HEAP_NUMBER_OF_PSEUDO_TAG + Heap->NextAvailableTagIndex + 1) *
sizeof( SIZE_T );
02159
02160
if ((
RtlpValidateHeapTagsEnable) && (Heap->PseudoTagEntries !=
NULL)) {
02161
02162
Status =
NtAllocateVirtualMemory( NtCurrentProcess(),
02163 &ComputedPseudoTagEntries,
02164 0,
02165 &
Size,
02166 MEM_COMMIT,
02167 PAGE_READWRITE );
02168
02169
if (
NT_SUCCESS(
Status )) {
02170
02171 ComputedTagEntries = ComputedPseudoTagEntries +
HEAP_NUMBER_OF_PSEUDO_TAG;
02172 }
02173 }
02174
02175 Head = &Heap->VirtualAllocdBlocks;
02176 Next = Head->Flink;
02177
02178
while (Head != Next) {
02179
02180 VirtualAllocBlock = CONTAINING_RECORD( Next,
HEAP_VIRTUAL_ALLOC_ENTRY, Entry );
02181
02182
if (ComputedTagEntries !=
NULL) {
02183
02184 TagIndex = VirtualAllocBlock->
ExtraStuff.
TagIndex;
02185
02186
if (TagIndex != 0) {
02187
02188
if (TagIndex & HEAP_PSEUDO_TAG_FLAG) {
02189
02190 TagIndex &= ~HEAP_PSEUDO_TAG_FLAG;
02191
02192
if (TagIndex <
HEAP_NUMBER_OF_PSEUDO_TAG) {
02193
02194 ComputedPseudoTagEntries[ TagIndex ] +=
02195 VirtualAllocBlock->
CommitSize >>
HEAP_GRANULARITY_SHIFT;
02196 }
02197
02198 }
else if (TagIndex & HEAP_GLOBAL_TAG) {
02199
02200
02201
02202
02203
02204
02205 }
else if (TagIndex < Heap->NextAvailableTagIndex) {
02206
02207 ComputedTagEntries[ TagIndex ] +=
02208 VirtualAllocBlock->
CommitSize >>
HEAP_GRANULARITY_SHIFT;
02209 }
02210 }
02211 }
02212
02213
if (VirtualAllocBlock->
BusyBlock.
Flags &
HEAP_ENTRY_FILL_PATTERN) {
02214
02215
if (!
RtlpCheckBusyBlockTail( &VirtualAllocBlock->
BusyBlock )) {
02216
02217
return FALSE;
02218 }
02219 }
02220
02221 Next = Next->Flink;
02222 }
02223
02224 CountOfFreeBlocks = 0;
02225 TotalFreeSize = 0;
02226
02227
for (SegmentIndex=0; SegmentIndex<
HEAP_MAXIMUM_SEGMENTS; SegmentIndex++) {
02228
02229 Segment = Heap->Segments[ SegmentIndex ];
02230
02231
if (Segment) {
02232
02233
if (!
RtlpValidateHeapSegment( Heap,
02234 Segment,
02235 SegmentIndex,
02236 &CountOfFreeBlocks,
02237 &TotalFreeSize,
02238 &BadAddress,
02239 ComputedTagEntries,
02240 ComputedPseudoTagEntries )) {
02241
02242
goto errorExit;
02243 }
02244 }
02245 }
02246
02247 BadAddress = Heap;
02248
02249
if (NumberOfFreeListEntries != CountOfFreeBlocks) {
02250
02251
HeapDebugPrint((
"Number of free blocks in arena (%ld) does not match number in the free lists (%ld)\n",
02252 CountOfFreeBlocks,
02253 NumberOfFreeListEntries ));
02254
02255
goto errorExit;
02256 }
02257
02258
if (Heap->TotalFreeSize != TotalFreeSize) {
02259
02260
HeapDebugPrint((
"Total size of free blocks in arena (%ld) does not match number total in heap header (%ld)\n",
02261 TotalFreeSize,
02262 Heap->TotalFreeSize ));
02263
02264
goto errorExit;
02265 }
02266
02267
if (ComputedPseudoTagEntries !=
NULL) {
02268
02269
PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries;
02270
PHEAP_TAG_ENTRY TagEntries;
02271
USHORT TagIndex;
02272
02273 PseudoTagEntries = Heap->PseudoTagEntries;
02274
02275
if (PseudoTagEntries !=
NULL) {
02276
02277
for (TagIndex=1; TagIndex<
HEAP_NUMBER_OF_PSEUDO_TAG; TagIndex++) {
02278
02279 PseudoTagEntries += 1;
02280
02281
if (ComputedPseudoTagEntries[ TagIndex ] != PseudoTagEntries->
Size) {
02282
02283
HeapDebugPrint((
"Pseudo Tag %04x size incorrect (%x != %x) %x\n",
02284 TagIndex,
02285 PseudoTagEntries->
Size,
02286 ComputedPseudoTagEntries[ TagIndex ]
02287 &ComputedPseudoTagEntries[ TagIndex ] ));
02288
02289
goto errorExit;
02290 }
02291 }
02292 }
02293
02294 TagEntries = Heap->TagEntries;
02295
02296
if (TagEntries !=
NULL) {
02297
02298
for (TagIndex=1; TagIndex<Heap->NextAvailableTagIndex; TagIndex++) {
02299
02300 TagEntries += 1;
02301
02302
if (ComputedTagEntries[ TagIndex ] != TagEntries->
Size) {
02303
02304
HeapDebugPrint((
"Tag %04x (%ws) size incorrect (%x != %x) %x\n",
02305 TagIndex,
02306 TagEntries->
TagName,
02307 TagEntries->
Size,
02308 ComputedTagEntries[ TagIndex ],
02309 &ComputedTagEntries[ TagIndex ] ));
02310
02311
goto errorExit;
02312 }
02313 }
02314 }
02315
02316
Size = 0;
02317
02318
NtFreeVirtualMemory( NtCurrentProcess(),
02319 &ComputedPseudoTagEntries,
02320 &
Size,
02321 MEM_RELEASE );
02322 }
02323
02324
exit:
02325
02326
return TRUE;
02327
02328 errorExit:
02329
02330
HeapDebugBreak( BadAddress );
02331
02332
if (ComputedPseudoTagEntries !=
NULL) {
02333
02334
Size = 0;
02335
02336
NtFreeVirtualMemory( NtCurrentProcess(),
02337 &ComputedPseudoTagEntries,
02338 &
Size,
02339 MEM_RELEASE );
02340 }
02341
02342
return FALSE;
02343
02344 }
02345
02346
02347 BOOLEAN
RtlpHeapInvalidBreakPoint;
02348 PVOID
RtlpHeapInvalidBadAddress;
02349
02350
VOID
02351 RtlpBreakPointHeap (
02352 IN PVOID BadAddress
02353 )
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365 {
02366
if (NtCurrentPeb()->BeingDebugged) {
02367
02368 *(BOOLEAN
volatile *)&
RtlpHeapInvalidBreakPoint =
TRUE;
02369
02370
RtlpHeapInvalidBadAddress = BadAddress;
02371
02372 DbgBreakPoint();
02373
02374 *(BOOLEAN
volatile *)&
RtlpHeapInvalidBreakPoint =
FALSE;
02375 }
02376 }